semmy 0.4.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -22
- data/README.md +114 -49
- data/lib/semmy/changelog.rb +64 -17
- data/lib/semmy/configuration.rb +4 -4
- data/lib/semmy/tasks.rb +10 -0
- data/lib/semmy/tasks/changelog_sections.rb +17 -0
- data/lib/semmy/tasks/versioning.rb +18 -0
- data/lib/semmy/version.rb +1 -1
- data/lib/semmy/version_string.rb +27 -16
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2863f4f726ca7e693eb807b85361216b13d6888
|
4
|
+
data.tar.gz: 25ea8f2c9cd7e1800e6b5aac5b183df255d2d8ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1182968ffa50bdc64b6023186cf8ef994dab8aa39c61c408a2822c2e07163860bba9f3b987911b47f613fb93eb61fb0267a104bbf7c10b03425d08a05501d4e2
|
7
|
+
data.tar.gz: e2fd0ec272420a10a2e4e8f2698e5120986eccec10b8c311b703a88ef1cf6e0402cf5c6187cfebb21669a178abf72b3cd8cc84006ab11455b4ede10e16cd9704
|
data/CHANGELOG.md
CHANGED
@@ -1,34 +1,28 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
-
### Version 0.
|
3
|
+
### Version 1.0.0
|
4
4
|
|
5
5
|
2017-07-13
|
6
6
|
|
7
|
-
[Compare changes](https://github.com/tf/semmy/compare/0-
|
7
|
+
[Compare changes](https://github.com/tf/semmy/compare/0-x-stable...v1.0.0)
|
8
8
|
|
9
|
-
|
10
|
-
to previous stable branch.
|
11
|
-
- Compare minor versions to previous stable branch.
|
9
|
+
##### Breaking Changes
|
12
10
|
|
13
|
-
|
11
|
+
- A typo in the name of the `changelog_unreleased_section_heading` and
|
12
|
+
`changelog_unreleased_section_blank_slate` options was fixed.
|
13
|
+
- The default value of `changelog_unreleased_section_heading` changed
|
14
|
+
to "Unreleased Changes". You need to update the header in your
|
15
|
+
changelog or manually set the previous value via the configuration option.
|
14
16
|
|
15
|
-
|
17
|
+
##### New Features
|
16
18
|
|
17
|
-
|
19
|
+
- Add `bump:patch` task which begins a patch level release.
|
20
|
+
- Add `bump:mahor` task which updates the major version.
|
18
21
|
|
19
|
-
|
20
|
-
- Add link comparing to last patch level for stable release.
|
22
|
+
##### Bug Fixes
|
21
23
|
|
22
|
-
|
24
|
+
- Fix indentation of generated unreleased changes section.
|
23
25
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
- Fine tune default commit messages.
|
29
|
-
|
30
|
-
### Version 0.1.0
|
31
|
-
|
32
|
-
2016-06-09
|
33
|
-
|
34
|
-
- Initial release
|
26
|
+
See
|
27
|
+
[0-x-stable branch](https://github.com/tf/semmy/blob/0-x-stable/CHANGELOG.md)
|
28
|
+
for previous changes.
|
data/README.md
CHANGED
@@ -9,12 +9,52 @@
|
|
9
9
|
An opinionated set of rake tasks to maintain gems following semantic
|
10
10
|
versioning principles.
|
11
11
|
|
12
|
+
## Assumptions
|
13
|
+
|
14
|
+
### Git Branches and Tags
|
15
|
+
|
16
|
+
Development happens directly on `master` or by merging pull
|
17
|
+
requests. When a release is made, a stable branch called `x-y-stable`
|
18
|
+
is created. Semmy relies on Bundler's `release` task to create version
|
19
|
+
tags.
|
20
|
+
|
21
|
+
Patch level versions are released via backports to the stable
|
22
|
+
branches.
|
23
|
+
|
24
|
+
### Version Suffix
|
25
|
+
|
26
|
+
The version in the gem's version file is increased in a separate
|
27
|
+
commit right after release. The version always has an `dev` suffix
|
28
|
+
(i.e. `1.1.0.dev`), which is only removed in the last commit
|
29
|
+
preparing the release. That way it is easy to see in a project's
|
30
|
+
`Gemfile.lock` whether an unreleased version is used.
|
31
|
+
|
32
|
+
Patch level versions are expected to be released immediately after
|
33
|
+
backporting bug fixes. So there are never commits with a version
|
34
|
+
suffix on stable branches.
|
35
|
+
|
36
|
+
### Doc Tags
|
37
|
+
|
38
|
+
Pull requests introducing new features, are expected to markup new
|
39
|
+
code elements with a `@since edge` doc tag. When a release is
|
40
|
+
prepared, `edge` is replaced with the current version string. That way
|
41
|
+
pull request authors do not have to guess, which version will merge
|
42
|
+
their commits.
|
43
|
+
|
44
|
+
### Changelog
|
45
|
+
|
46
|
+
Unreleased changes are listed in a section at the top. When preparing
|
47
|
+
a release this section is closed by placing a version heading above it
|
48
|
+
and inserting a compare link. Changelog entries for patch level
|
49
|
+
versions are only committed on the stable branches since they only
|
50
|
+
backport bug fixes from master.
|
51
|
+
|
12
52
|
## Installation
|
13
53
|
|
14
54
|
Add development dependency to your gemspec:
|
15
55
|
|
16
56
|
# your.gemspec
|
17
|
-
s.add_development_dependency 'semmy', '~> 0
|
57
|
+
s.add_development_dependency 'semmy', '~> 1.0'
|
18
58
|
|
19
59
|
Install gems:
|
20
60
|
|
@@ -35,10 +75,11 @@ Semmy defines a new task to prepare a release:
|
|
35
75
|
|
36
76
|
This task:
|
37
77
|
|
38
|
-
*
|
39
|
-
*
|
78
|
+
* Ensures the gem can be installed.
|
79
|
+
* Removes the `dev` version suffix from the version file.
|
80
|
+
* Rewrites doc tags.
|
40
81
|
* Closes the section of the new version in the changelog.
|
41
|
-
* Commits the changes
|
82
|
+
* Commits the changes.
|
42
83
|
|
43
84
|
It is expected that a `release` task exists. Normally this tasks is
|
44
85
|
provided by Bundler.
|
@@ -48,67 +89,91 @@ provided by Bundler.
|
|
48
89
|
Semmy registers additional actions which shall be
|
49
90
|
executed right after the release:
|
50
91
|
|
51
|
-
* Creates a stable branch
|
92
|
+
* Creates a stable branch.
|
52
93
|
* Bumps the version to the next minor version with `alpha` version
|
53
94
|
suffix.
|
54
|
-
* Inserts an "Changes
|
95
|
+
* Inserts an "Unreleased Changes" section in the changelog.
|
55
96
|
|
56
|
-
|
97
|
+
The resulting commit graph looks like:
|
57
98
|
|
58
|
-
|
99
|
+
* (master) Bump version to 1.3.0.dev
|
100
|
+
* (v1.2.0, 1-2-stable) Prepare 1.2.0 release
|
101
|
+
* Some new feature
|
59
102
|
|
60
|
-
|
61
|
-
requests. When a release is made, a stable branch called `x-y-stable`
|
62
|
-
is created. Semmy relies on Bundler's `release` task to create version
|
63
|
-
tags.
|
103
|
+
### Releasing a Patch Level Version
|
64
104
|
|
65
|
-
|
66
|
-
branches.
|
105
|
+
Assume an important bug fix has been added to `master`:
|
67
106
|
|
68
|
-
|
107
|
+
* (master) Important bug fix
|
108
|
+
* First new feature
|
109
|
+
* Bump version to 1.3.0.dev
|
110
|
+
* (v1.0.0, 1-2-stable) Prepare 1.2.0 release
|
69
111
|
|
70
|
-
|
71
|
-
commit right after release. The version always has an `alpha` suffix
|
72
|
-
(i.e. `1.1.0.alpha`), which is only removed in the last commit
|
73
|
-
preparing the release. That way it is easy to see in a project's
|
74
|
-
`Gemfile.lock` whether an unreleased version is used.
|
112
|
+
check out the stable branch and cherry pick commits:
|
75
113
|
|
76
|
-
|
77
|
-
|
78
|
-
suffix on stable branches.
|
114
|
+
$ git checkout 1-2-stable
|
115
|
+
$ git cherry-pick master
|
79
116
|
|
80
|
-
|
117
|
+
Then run:
|
81
118
|
|
82
|
-
|
83
|
-
code elements with a `@since edge` doc tag. When a release is
|
84
|
-
prepared, `edge` is replaced with the current version string. That way
|
85
|
-
pull request authors do not have to guess, which version will merge
|
86
|
-
their commits.
|
119
|
+
$ rake bump:patch
|
87
120
|
|
88
|
-
|
121
|
+
This task:
|
89
122
|
|
90
|
-
|
91
|
-
|
92
|
-
and inserting a compare link. Changelog entries for patch level
|
93
|
-
versions are only committed on the stable branches since they only
|
94
|
-
backport bug fixes from master.
|
123
|
+
* Bumps the version to `1.2.1` in the version file.
|
124
|
+
* Inserts an "Unreleased Changes" section in the changelog.
|
95
125
|
|
96
|
-
|
126
|
+
Add items to the new changelog section, then run:
|
97
127
|
|
98
|
-
|
128
|
+
$ rake release:prepare
|
99
129
|
|
100
|
-
|
101
|
-
|
102
|
-
3: * First new feature
|
103
|
-
4: * Important bug fix
|
104
|
-
5: * Begin work on 1.1
|
105
|
-
6: | * (1-0-stable, v1.0.2) Prepare 1.0.2 release
|
106
|
-
7: | * Backport of other bug fix
|
107
|
-
8: | * (v1.0.1) Prepare 1.0.1 release
|
108
|
-
9: | * Backport of important bug fix
|
109
|
-
10: |/
|
110
|
-
11: * (v1.0.0) Prepare 1.0.0 release
|
130
|
+
This task detects that we are currently on a stable branch and
|
131
|
+
performs the following subset of the normal prepare tasks:
|
111
132
|
|
112
|
-
|
133
|
+
* Closes the section of the new version in the changelog.
|
134
|
+
* Commits the changes
|
135
|
+
|
136
|
+
You can now run `rake release`, leaving you with the following commit
|
137
|
+
graph:
|
138
|
+
|
139
|
+
* (master) Important bug fix
|
140
|
+
* First new feature
|
141
|
+
* Bump version to 1.3.0.dev
|
142
|
+
| * (v1.2.1, 1-2-stable) Prepare 1.2.1 release
|
143
|
+
| * Important bug fix
|
144
|
+
|/
|
145
|
+
* (v1.2.0) Prepare 1.2.0 release
|
146
|
+
|
147
|
+
### Releasing a Major Version
|
148
|
+
|
149
|
+
If breaking changes have been merged to master, run:
|
150
|
+
|
151
|
+
$ rake bump:major
|
152
|
+
|
153
|
+
Assuming the version was `1.2.0.dev` before, This bumps the major
|
154
|
+
version in the version file to `2.0.0.dev` and updates the changelog
|
155
|
+
to reference `1-x-stable` for comparison.
|
156
|
+
|
157
|
+
The branch `1-x-stable` has to be created and managed manually. It
|
158
|
+
should always point to the same commit as the lastest minor version
|
159
|
+
stable branch of the major version.
|
160
|
+
|
161
|
+
The rest of the release can be performed like a normal minor version
|
162
|
+
release.
|
163
|
+
|
164
|
+
## Development
|
165
|
+
|
166
|
+
After checking out the repo, run `bin/setup` to install
|
167
|
+
dependencies. You can also run `bin/console` for an interactive prompt
|
168
|
+
that will allow you to experiment. Run `bin/rspec` to execute the test
|
169
|
+
suite.
|
170
|
+
|
171
|
+
## Contributing
|
172
|
+
|
173
|
+
Bug reports and pull requests are welcome on GitHub at
|
174
|
+
https://github.com/tf/semmy.
|
113
175
|
|
176
|
+
## License
|
114
177
|
|
178
|
+
The gem is available as open source under the terms of the
|
179
|
+
[MIT License](http://opensource.org/licenses/MIT).
|
data/lib/semmy/changelog.rb
CHANGED
@@ -22,7 +22,7 @@ module Semmy
|
|
22
22
|
private
|
23
23
|
|
24
24
|
def unreleased_section_matcher
|
25
|
-
/#{config.
|
25
|
+
/#{config.changelog_unreleased_section_heading}(\s*#{compare_link_matcher})?/
|
26
26
|
end
|
27
27
|
|
28
28
|
def compare_link_matcher
|
@@ -72,7 +72,7 @@ module Semmy
|
|
72
72
|
|
73
73
|
UpdateForMinor = Struct.new(:config, :options) do
|
74
74
|
def call(contents)
|
75
|
-
replace_starting_at(version_line_matcher,
|
75
|
+
replace_starting_at(Changelog.version_line_matcher(config),
|
76
76
|
contents,
|
77
77
|
unreleased_section)
|
78
78
|
end
|
@@ -80,15 +80,26 @@ module Semmy
|
|
80
80
|
private
|
81
81
|
|
82
82
|
def unreleased_section
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
83
|
+
# Once Ruby < 2.3 support is dropped, this can be rewritten
|
84
|
+
# as:
|
85
|
+
#
|
86
|
+
# <<~END
|
87
|
+
# #{config.changelog_unreleased_section_heading}
|
88
|
+
#
|
89
|
+
# #{compare_link_for_master}
|
90
|
+
#
|
91
|
+
# #{config.changelog_unreleased_section_blank_slate}
|
92
|
+
#
|
93
|
+
# #{link_to_changelog_on_previous_minor_stable_branch}
|
94
|
+
# END
|
95
|
+
#
|
96
|
+
# `unindent` cannot handle line breaks in interpolated values correctly.
|
97
|
+
[
|
98
|
+
config.changelog_unreleased_section_heading,
|
99
|
+
compare_link_for_master,
|
100
|
+
config.changelog_unreleased_section_blank_slate,
|
101
|
+
link_to_changelog_on_previous_minor_stable_branch
|
102
|
+
].join("\n\n") << "\n"
|
92
103
|
end
|
93
104
|
|
94
105
|
def compare_link_for_master
|
@@ -112,12 +123,6 @@ module Semmy
|
|
112
123
|
config.stable_branch_name)
|
113
124
|
end
|
114
125
|
|
115
|
-
def version_line_matcher
|
116
|
-
Regexp.new(config.changelog_version_section_heading % {
|
117
|
-
version: '([0-9.]+)'
|
118
|
-
})
|
119
|
-
end
|
120
|
-
|
121
126
|
def replace_starting_at(line_matcher, text, inserted_text)
|
122
127
|
unless text =~ line_matcher
|
123
128
|
fail(InsertPointNotFound, 'Insert point not found.')
|
@@ -127,10 +132,52 @@ module Semmy
|
|
127
132
|
end
|
128
133
|
end
|
129
134
|
|
135
|
+
InsertUnreleasedSection = Struct.new(:config) do
|
136
|
+
def call(contents)
|
137
|
+
insert_before(Changelog.version_line_matcher(config),
|
138
|
+
contents,
|
139
|
+
config.changelog_unreleased_section_heading << "\n")
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
def insert_before(line_matcher, text, inserted_text)
|
145
|
+
text.dup.tap do |result|
|
146
|
+
unless (result.sub!(line_matcher, inserted_text + "\n\\0"))
|
147
|
+
fail(InsertPointNotFound,
|
148
|
+
'Insert point not found.')
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
ReplaceMinorStableBranchWithMajorStableBranch = Struct.new(:config, :options) do
|
155
|
+
def call(contents)
|
156
|
+
contents.gsub(minor_stable_branch(options[:version]),
|
157
|
+
major_stable_branch(options[:version]))
|
158
|
+
end
|
159
|
+
|
160
|
+
private
|
161
|
+
|
162
|
+
def minor_stable_branch(version)
|
163
|
+
VersionString.previous_stable_branch_name(version, config.stable_branch_name)
|
164
|
+
end
|
165
|
+
|
166
|
+
def major_stable_branch(version)
|
167
|
+
config.stable_branch_name % VersionString.components(version).merge(minor: 'x')
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
130
171
|
def version_tag(version)
|
131
172
|
"v#{version}"
|
132
173
|
end
|
133
174
|
|
175
|
+
def version_line_matcher(config)
|
176
|
+
Regexp.new(config.changelog_version_section_heading % {
|
177
|
+
version: '([0-9.]+)'
|
178
|
+
})
|
179
|
+
end
|
180
|
+
|
134
181
|
def compare_link(config, interpolations)
|
135
182
|
"[Compare changes](#{compare_url(config, interpolations)})"
|
136
183
|
end
|
data/lib/semmy/configuration.rb
CHANGED
@@ -14,8 +14,8 @@ module Semmy
|
|
14
14
|
|
15
15
|
attr_accessor :changelog_path
|
16
16
|
attr_accessor :changelog_version_section_heading
|
17
|
-
attr_accessor :
|
18
|
-
attr_accessor :
|
17
|
+
attr_accessor :changelog_unreleased_section_heading
|
18
|
+
attr_accessor :changelog_unreleased_section_blank_slate
|
19
19
|
attr_accessor :changelog_previous_changes_link
|
20
20
|
|
21
21
|
attr_accessor :source_files_with_docs_tags
|
@@ -34,8 +34,8 @@ module Semmy
|
|
34
34
|
|
35
35
|
@changelog_path = 'CHANGELOG.md'
|
36
36
|
@changelog_version_section_heading = '### Version %{version}'
|
37
|
-
@
|
38
|
-
@
|
37
|
+
@changelog_unreleased_section_heading = '### Unreleased Changes'
|
38
|
+
@changelog_unreleased_section_blank_slate = 'None so far.'
|
39
39
|
@changelog_previous_changes_link = "See\n[%{branch} branch](%{url})\nfor previous changes."
|
40
40
|
|
41
41
|
@source_files_with_docs_tags = '{app,lib}/**/*.{js,rb,scss}'
|
data/lib/semmy/tasks.rb
CHANGED
@@ -66,6 +66,16 @@ module Semmy
|
|
66
66
|
task 'release' do
|
67
67
|
Rake.application['release:after'].invoke
|
68
68
|
end
|
69
|
+
|
70
|
+
task 'bump:patch' => [
|
71
|
+
'semmy:versioning:bump_patch_level',
|
72
|
+
'semmy:changelog:insert_unreleased_section'
|
73
|
+
]
|
74
|
+
|
75
|
+
task 'bump:major' => [
|
76
|
+
'semmy:changelog:replace_minor_stable_branch_with_major_stable_branch',
|
77
|
+
'semmy:versioning:bump_major'
|
78
|
+
]
|
69
79
|
end
|
70
80
|
end
|
71
81
|
end
|
@@ -26,6 +26,23 @@ module Semmy
|
|
26
26
|
version: Project.version,
|
27
27
|
homepage: Gemspec.homepage))
|
28
28
|
end
|
29
|
+
|
30
|
+
task 'replace_minor_stable_branch_with_major_stable_branch' do
|
31
|
+
Shell.info('Updating changelog ' \
|
32
|
+
"in #{config.changelog_path}.")
|
33
|
+
|
34
|
+
Files.rewrite(config.changelog_path,
|
35
|
+
Changelog::ReplaceMinorStableBranchWithMajorStableBranch
|
36
|
+
.new(config, version: Project.version))
|
37
|
+
end
|
38
|
+
|
39
|
+
task 'insert_unreleased_section' do
|
40
|
+
Shell.info('Inserting unreleased changes header ' \
|
41
|
+
"in #{config.changelog_path}.")
|
42
|
+
|
43
|
+
Files.rewrite(config.changelog_path,
|
44
|
+
Changelog::InsertUnreleasedSection.new(config))
|
45
|
+
end
|
29
46
|
end
|
30
47
|
end
|
31
48
|
end
|
@@ -13,6 +13,15 @@ module Semmy
|
|
13
13
|
rewrite_gemspec_version(new_version)
|
14
14
|
end
|
15
15
|
|
16
|
+
task 'bump_major' do
|
17
|
+
new_version = VersionString
|
18
|
+
.bump_major(Project.version, config.development_version_suffix)
|
19
|
+
|
20
|
+
Shell.info("Bumping version to #{new_version}.")
|
21
|
+
|
22
|
+
rewrite_gemspec_version(new_version)
|
23
|
+
end
|
24
|
+
|
16
25
|
task 'bump_minor' do
|
17
26
|
new_version = VersionString
|
18
27
|
.bump_minor(Project.version, config.development_version_suffix)
|
@@ -21,6 +30,15 @@ module Semmy
|
|
21
30
|
|
22
31
|
rewrite_gemspec_version(new_version)
|
23
32
|
end
|
33
|
+
|
34
|
+
task 'bump_patch_level' do
|
35
|
+
new_version = VersionString
|
36
|
+
.bump_patch_level(Project.version)
|
37
|
+
|
38
|
+
Shell.info("Bumping version to #{new_version}.")
|
39
|
+
|
40
|
+
rewrite_gemspec_version(new_version)
|
41
|
+
end
|
24
42
|
end
|
25
43
|
end
|
26
44
|
|
data/lib/semmy/version.rb
CHANGED
data/lib/semmy/version_string.rb
CHANGED
@@ -18,18 +18,16 @@ module Semmy
|
|
18
18
|
new_version
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
24
|
-
unless components.last =~ /^[0-9]+$/
|
25
|
-
fail(UnexpectedSuffix, "Expected a version without suffix, found #{version}.")
|
26
|
-
end
|
21
|
+
def bump_major(version, suffix)
|
22
|
+
[bump(0, version), suffix].join('.')
|
23
|
+
end
|
27
24
|
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
def bump_minor(version, suffix)
|
26
|
+
[bump(1, version), suffix].join('.')
|
27
|
+
end
|
31
28
|
|
32
|
-
|
29
|
+
def bump_patch_level(version)
|
30
|
+
bump(2, version)
|
33
31
|
end
|
34
32
|
|
35
33
|
def minor_only(version)
|
@@ -70,17 +68,30 @@ module Semmy
|
|
70
68
|
|
71
69
|
private
|
72
70
|
|
71
|
+
def bump(component_index, version)
|
72
|
+
components = version.split('.')[0..2].map!(&:to_i)
|
73
|
+
|
74
|
+
[
|
75
|
+
components[0...component_index],
|
76
|
+
components[component_index] + 1,
|
77
|
+
[0] * (2 - component_index)
|
78
|
+
].flatten.join('.')
|
79
|
+
end
|
80
|
+
|
73
81
|
def previous_minor_version_components(version)
|
74
82
|
components = version.split('.').map(&:to_i)
|
75
83
|
|
76
84
|
if components[1].zero?
|
77
|
-
|
85
|
+
{
|
86
|
+
major: components[0] - 1,
|
87
|
+
minor: 'x'
|
88
|
+
}
|
89
|
+
else
|
90
|
+
{
|
91
|
+
major: components[0],
|
92
|
+
minor: components[1] - 1
|
93
|
+
}
|
78
94
|
end
|
79
|
-
|
80
|
-
{
|
81
|
-
major: components[0],
|
82
|
-
minor: components[1] - 1
|
83
|
-
}
|
84
95
|
end
|
85
96
|
end
|
86
97
|
end
|