├── lib
├── conventional_changelog
│ ├── version.rb
│ ├── cli.rb
│ ├── generator.rb
│ ├── by_version_writer.rb
│ ├── by_date_writer.rb
│ ├── git.rb
│ └── writer.rb
└── conventional_changelog.rb
├── Rakefile
├── Gemfile
├── bin
└── conventional-changelog
├── .gitignore
├── .travis.yml
├── spec
├── spec_helper.rb
├── git_spec.rb
├── cli_spec.rb
└── generator_spec.rb
├── LICENSE.txt
├── conventional-changelog.gemspec
├── CHANGELOG.md
└── README.md
/lib/conventional_changelog/version.rb:
--------------------------------------------------------------------------------
1 | module ConventionalChangelog
2 | VERSION = "1.3.0"
3 | end
4 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require "bundler/gem_tasks"
2 | require 'rspec/core/rake_task'
3 | RSpec::Core::RakeTask.new(:spec)
4 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | # Specify your gem's dependencies in conventional-changelog.gemspec
4 | gemspec
5 |
--------------------------------------------------------------------------------
/bin/conventional-changelog:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require 'rubygems'
3 | require 'conventional_changelog'
4 | require 'conventional_changelog/cli'
5 | ConventionalChangelog::CLI.execute ARGV
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.bundle/
2 | /.yardoc
3 | /Gemfile.lock
4 | /_yardoc/
5 | /coverage/
6 | /doc/
7 | /pkg/
8 | /spec/reports/
9 | /tmp/
10 | *.bundle
11 | *.so
12 | *.o
13 | *.a
14 | mkmf.log
15 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | addons:
2 | code_climate:
3 | repo_token: 70c8e7caf52d56ab9ea35d2d9f30c4ab28431647b05d35edbe889eaec8803056
4 | language: ruby
5 | rvm:
6 | - "2.1.5"
7 | - "2.2.1"
8 | script: bundle exec rake spec
9 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | require "codeclimate-test-reporter"
2 | CodeClimate::TestReporter.start
3 | require 'pp'
4 | require 'fakefs'
5 | require 'conventional_changelog'
6 |
7 | RSpec.configure do |config|
8 | config.before(:all) { FakeFS.activate! }
9 | config.after(:all) { FakeFS.deactivate! }
10 | end
11 |
--------------------------------------------------------------------------------
/lib/conventional_changelog/cli.rb:
--------------------------------------------------------------------------------
1 | module ConventionalChangelog
2 | class CLI
3 | def self.execute(params)
4 | Generator.new.generate! parse(params)
5 | end
6 |
7 | def self.parse(params)
8 | Hash[*params.map { |param| param.split("=") }.map { |key, value| [key.to_sym, value] }.flatten]
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/lib/conventional_changelog/generator.rb:
--------------------------------------------------------------------------------
1 | module ConventionalChangelog
2 | class Generator
3 | def generate!(options = {})
4 | writer(options).new("CHANGELOG.md").write! options
5 | end
6 |
7 | private
8 |
9 | def writer(options)
10 | options[:version] ? ByVersionWriter : ByDateWriter
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/lib/conventional_changelog.rb:
--------------------------------------------------------------------------------
1 | require "conventional_changelog/generator"
2 | require "conventional_changelog/git"
3 | require "conventional_changelog/version"
4 | require "conventional_changelog/writer"
5 | require "conventional_changelog/by_date_writer"
6 | require "conventional_changelog/by_version_writer"
7 |
8 | module ConventionalChangelog
9 | end
10 |
--------------------------------------------------------------------------------
/lib/conventional_changelog/by_version_writer.rb:
--------------------------------------------------------------------------------
1 | module ConventionalChangelog
2 | class ByVersionWriter < Writer
3 | private
4 |
5 | def filter_key
6 | :since_version
7 | end
8 |
9 | def build_new_lines(options)
10 | write_section commits, options[:version]
11 | end
12 |
13 | def version_header_title(id)
14 | "#{id} (#{commits[0][:date]})"
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/lib/conventional_changelog/by_date_writer.rb:
--------------------------------------------------------------------------------
1 | module ConventionalChangelog
2 | class ByDateWriter < Writer
3 | private
4 |
5 | def filter_key
6 | :since_date
7 | end
8 |
9 | def build_new_lines(options)
10 | commits.group_by { |commit| commit[:date] }.sort.reverse_each do |date, commits|
11 | write_section commits, date
12 | end
13 | end
14 |
15 | def version_header_title(id)
16 | id
17 | end
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/spec/git_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe ConventionalChangelog::Git do
4 | subject { ConventionalChangelog::Git }
5 |
6 | describe ".log" do
7 | it "returns a log with default options" do
8 | log = subject.log({})
9 |
10 | expect(log).to include "feat(bin): add a conventional-changelog binary"
11 | end
12 |
13 | it "raises an exception if Git returns an error" do
14 | expect do
15 | subject.log({ since_version: 'invalid-branch' })
16 | end.to raise_exception RuntimeError, "Can't load Git commits, check your arguments"
17 | end
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/spec/cli_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'conventional_changelog/cli'
3 |
4 | describe ConventionalChangelog::CLI do
5 | describe ".execute" do
6 | it 'runs clean' do
7 | expect { ConventionalChangelog::CLI.execute [] }.to_not raise_exception
8 | end
9 |
10 | context "with empty arguments" do
11 | it 'generates a changelog' do
12 | expect_any_instance_of(ConventionalChangelog::Generator).to receive(:generate!).with({})
13 | ConventionalChangelog::CLI.execute []
14 | end
15 | end
16 |
17 | context "with version=x.y.z" do
18 | it 'generates a changelog with the version' do
19 | expect_any_instance_of(ConventionalChangelog::Generator).to receive(:generate!).with version: "x.y.z"
20 | ConventionalChangelog::CLI.execute ["version=x.y.z"]
21 | end
22 | end
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015 Diego Carrion
2 |
3 | MIT License
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | "Software"), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/lib/conventional_changelog/git.rb:
--------------------------------------------------------------------------------
1 | require 'open3'
2 |
3 | module ConventionalChangelog
4 | class Git
5 | DELIMITER = "/////"
6 |
7 | def self.commits(options)
8 | log(options).split("\n").map { |commit| commit.split DELIMITER }.select { |commit| options[:since_date].nil? or commit[1] > options[:since_date] }.map do |commit|
9 | comment = commit[2].match(/(\w*)(\(([\w\$\.\-\* ]*)\))?\: (.*)/)
10 | next unless comment
11 | { id: commit[0], date: commit[1], type: comment[1], component: comment[3], change: comment[4] }
12 | end.compact
13 | end
14 |
15 | def self.log(options)
16 | output, status = Open3.capture2(%Q{
17 | git log \
18 | --pretty=format:"%h#{DELIMITER}%ad#{DELIMITER}%s%x09" --date=short \
19 | --grep="^(feat|fix)(\\(.*\\))?:" -E \
20 | #{version_filter(options)}
21 | })
22 |
23 | if status.success?
24 | output
25 | else
26 | raise "Can't load Git commits, check your arguments"
27 | end
28 | end
29 |
30 | def self.version_filter(options)
31 | options[:since_version] ? "#{options[:since_version]}..HEAD" : ""
32 | end
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/conventional-changelog.gemspec:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 | lib = File.expand_path('../lib', __FILE__)
3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4 | require 'conventional_changelog/version'
5 |
6 | Gem::Specification.new do |spec|
7 | spec.name = "conventional-changelog"
8 | spec.version = ConventionalChangelog::VERSION
9 | spec.authors = ["Diego Carrion"]
10 | spec.email = ["dc.rec1@gmail.com"]
11 | spec.summary = %q{Ruby binary to generate a conventional changelog — Edit}
12 | spec.description = %q{}
13 | spec.homepage = "https://github.com/dcrec1/conventional-changelog-ruby"
14 | spec.license = "MIT"
15 |
16 | spec.files = `git ls-files -z`.split("\x0")
17 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19 | spec.require_paths = ["lib"]
20 |
21 | spec.add_development_dependency "bundler", "~> 1.7"
22 | spec.add_development_dependency "rake", "~> 10.0"
23 | spec.add_development_dependency "rspec", ">= 3.2"
24 | spec.add_development_dependency "fakefs"
25 | spec.add_development_dependency "codeclimate-test-reporter", "~> 0.1"
26 | end
27 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | ### 1.3.0 (2017-08-11)
3 |
4 |
5 | #### Features
6 |
7 | * skip unrecognizable commits ([81dd517](/../../commit/81dd517))
8 |
9 |
10 | #### Bug Fixes
11 |
12 | * ensure original content of file is maintained on error ([75f0529](/../../commit/75f0529))
13 | * do not add an extra new line at end of existing content ([cf52241](/../../commit/cf52241))
14 | * Allow last release id to be specified manually ([558def0](/../../commit/558def0))
15 | * Avoid truncating original changelog on errors ([4421e2c](/../../commit/4421e2c))
16 | * Handle empty output from Git ([628565d](/../../commit/628565d))
17 | * change mocked code to correctly return commits without scope ([e1b9bf8](/../../commit/e1b9bf8))
18 |
19 |
20 |
21 | ### v1.2.0 (2015-03-31)
22 |
23 |
24 | #### Features
25 |
26 | * **output**
27 | * support commits without scope ([3b127d7](/../../commit/3b127d7))
28 |
29 |
30 |
31 | ### v1.1.0 (2015-03-29)
32 |
33 |
34 | #### Features
35 |
36 | * **output**
37 | * add a link to the change id ([c027a8f](/../../commit/c027a8f))
38 |
39 | * **bin**
40 | * conventional-changelog accepts a version=x.y.z param ([ccc8eec](/../../commit/ccc8eec))
41 |
42 | * **api**
43 | * Generator#generate accepts a version param ([69f8f72](/../../commit/69f8f72))
44 |
45 |
46 |
47 | ### v1.0.0 (2015-03-28)
48 |
49 |
50 | #### Features
51 |
52 | * **api**
53 | * Generator#generate! generates a changelog programatically ([9738c30](/../../commit/9738c30))
54 |
55 | * **bin**
56 | * add a conventional-changelog binary ([af6be02](/../../commit/af6be02))
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/dcrec1/conventional-changelog-ruby)
2 | [](https://codeclimate.com/github/dcrec1/conventional-changelog-ruby)
3 | [](https://codeclimate.com/github/dcrec1/conventional-changelog-ruby)
4 |
5 | # Conventional::Changelog
6 |
7 | Generates a CHANGELOG.md file from Git metadata using the AngularJS commit conventions.
8 |
9 | - [AngularJS Git Commit Message Conventions](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/)
10 |
11 | Since version 1.2.0 the scopes are optional.
12 |
13 |
14 | ## Installation
15 |
16 | $ gem install conventional-changelog
17 |
18 |
19 | ## Usage
20 |
21 | $ conventional-changelog
22 | $ conventional-changelog version=vX.Y.Z
23 |
24 | or programatically:
25 |
26 | ```ruby
27 | require 'conventional_changelog'
28 | ConventionalChangelog::Generator.new.generate!
29 | ConventionalChangelog::Generator.new.generate! version: "vX.Y.Z"
30 | ```
31 |
32 | Version param should follow your Git tags format
33 |
34 | ## Examples
35 |
36 | Converts this:
37 |
38 | 2015-03-30 feat(admin): increase reports ranges
39 | 2015-03-30 fix(api): fix annoying bug
40 | 2015-03-28 feat(api): add cool service
41 | 2015-03-28 feat(api): add cool feature
42 | 2015-03-28 feat(admin): add page to manage users
43 |
44 | into this:
45 |
46 |
47 | ### 2015-03-30
48 |
49 |
50 | #### Features
51 |
52 | * **admin**
53 | * increase reports ranges (4303fd4)
54 |
55 |
56 | #### Bug Fixes
57 |
58 | * **api**
59 | * fix annoying bug (4303fd5)
60 |
61 |
62 |
63 | ### 2015-03-28
64 |
65 |
66 | #### Features
67 |
68 | * **api**
69 | * add cool service (4303fd6)
70 | * add cool feature (4303fd7)
71 |
72 | * **admin**
73 | * add page to manage users (4303fd8)
74 |
75 | ## Contributing
76 |
77 | 1. Fork it ( https://github.com/dcrec1/conventional-changelog-ruby/fork )
78 | 2. Create your feature branch (`git checkout -b my-new-feature`)
79 | 3. Commit your changes (`git commit -am 'Add some feature'`)
80 | 4. Push to the branch (`git push origin my-new-feature`)
81 | 5. Create a new Pull Request
82 |
--------------------------------------------------------------------------------
/lib/conventional_changelog/writer.rb:
--------------------------------------------------------------------------------
1 | require 'stringio'
2 |
3 | module ConventionalChangelog
4 |
5 | class LastReleaseNotFound < StandardError
6 | MESSAGE = <<-EOM
7 | Could not determine last tag or release date from existing CHANGELOG.md.
8 | Please specify the last tag (eg. v1.2.3) or release date (eg. 2016-02-14)
9 | manually by setting the environment variable CONVENTIONAL_CHANGELOG_LAST_RELEASE
10 | and running the generate command again.
11 | EOM
12 |
13 | def initialize message = MESSAGE
14 | super(message)
15 | end
16 | end
17 |
18 | class Writer < File
19 | def initialize(file_name)
20 | FileUtils.touch file_name
21 | super file_name, 'r+'
22 |
23 | @new_body = StringIO.new
24 | @previous_body = read
25 | end
26 |
27 | def write!(options)
28 | build_new_lines options
29 | seek 0
30 | write @new_body.string
31 | write @previous_body
32 | end
33 |
34 | private
35 |
36 | def version_header(id)
37 | <<-HEADER
38 |
39 | ### #{version_header_title(id)}
40 |
41 | HEADER
42 | end
43 |
44 | def commits
45 | @commits ||= Git.commits filter_key => last_id
46 | end
47 |
48 | def append_changes(commits, type, title)
49 | unless (type_commits = commits.select { |commit| commit[:type] == type }).empty?
50 | @new_body.puts "#### #{title}", ""
51 | type_commits.group_by { |commit| commit[:component] }.each do |component, component_commits|
52 | @new_body.puts "* **#{component}**" if component
53 | component_commits.each { |commit| write_commit commit, component }
54 | @new_body.puts ""
55 | end
56 | end
57 | end
58 |
59 | def write_commit(commit, componentized)
60 | @new_body.puts "#{componentized ? ' ' : ''}* #{commit[:change]} ([#{commit[:id]}](/../../commit/#{commit[:id]}))"
61 | end
62 |
63 | def write_section(commits, id)
64 | return if commits.empty?
65 |
66 | @new_body.puts version_header(id)
67 | append_changes commits, "feat", "Features"
68 | append_changes commits, "fix", "Bug Fixes"
69 | end
70 |
71 | def last_id
72 | return nil if @previous_body.to_s.length == 0
73 | matches = @previous_body.split("\n")[0].to_s.match(/"(.*)"/)
74 |
75 | if matches
76 | matches[1]
77 | elsif manually_set_id = ENV['CONVENTIONAL_CHANGELOG_LAST_RELEASE']
78 | manually_set_id
79 | else
80 | raise LastReleaseNotFound.new
81 | end
82 | end
83 | end
84 | end
85 |
--------------------------------------------------------------------------------
/spec/generator_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe ConventionalChangelog::Generator do
4 | let(:changelog) { File.open("CHANGELOG.md").read }
5 |
6 | describe "#generate!" do
7 | before :each do
8 | FileUtils.rm "CHANGELOG.md", force: true
9 | end
10 |
11 | it 'runs clean' do
12 | expect { subject.generate! }.to_not raise_exception
13 | expect(changelog).to include "support commits without scope"
14 | expect(changelog).to include "change mocked code to correctly return commits without scope"
15 | end
16 |
17 | context "with no commits" do
18 | before :each do
19 | allow(ConventionalChangelog::Git).to receive(:log).and_return ""
20 | end
21 |
22 | it 'creates an empty changelog when no commits' do
23 | subject.generate!
24 | expect(changelog).to eql ""
25 | end
26 | end
27 |
28 | context "with merge commit" do
29 | before :each do
30 | allow(ConventionalChangelog::Git).to receive(:log).and_return log
31 | end
32 |
33 | context "skip merged commit" do
34 | let(:log) do <<-LOG
35 | 4303fd4/////2015-03-30/////feat(admin): increase reports ranges
36 | 430fa51/////2015-03-31/////Merge branch 'develop' into 'master'
37 | LOG
38 | end
39 |
40 | it 'does not contain merge commit' do
41 | subject.generate!
42 | body = <<-BODY
43 |
44 | ### 2015-03-30
45 |
46 | #### Features
47 |
48 | * **admin**
49 | * increase reports ranges ([4303fd4](/../../commit/4303fd4))
50 |
51 | BODY
52 | expect(changelog).to eql body
53 | end
54 | end
55 | end
56 |
57 | context "with multiple commits" do
58 | before :each do
59 | allow(ConventionalChangelog::Git).to receive(:log).and_return log
60 | end
61 |
62 | context "without a version param" do
63 | let(:log) do <<-LOG
64 | 4303fd4/////2015-03-30/////feat(admin): increase reports ranges
65 | 4303fd5/////2015-03-30/////fix(api): fix annoying bug
66 | 4303fd6/////2015-03-28/////feat(api): add cool service
67 | 4303fd7/////2015-03-28/////feat(api): add cool feature
68 | 4303fd8/////2015-03-28/////feat(admin): add page to manage users
69 | LOG
70 | end
71 |
72 |
73 | it 'parses simple lines into dates' do
74 | subject.generate!
75 | body = <<-BODY
76 |
77 | ### 2015-03-30
78 |
79 | #### Features
80 |
81 | * **admin**
82 | * increase reports ranges ([4303fd4](/../../commit/4303fd4))
83 |
84 | #### Bug Fixes
85 |
86 | * **api**
87 | * fix annoying bug ([4303fd5](/../../commit/4303fd5))
88 |
89 |
90 | ### 2015-03-28
91 |
92 | #### Features
93 |
94 | * **api**
95 | * add cool service ([4303fd6](/../../commit/4303fd6))
96 | * add cool feature ([4303fd7](/../../commit/4303fd7))
97 |
98 | * **admin**
99 | * add page to manage users ([4303fd8](/../../commit/4303fd8))
100 |
101 | BODY
102 | expect(changelog).to eql body
103 | end
104 |
105 | it 'preserves previous changes' do
106 | previous_body = <<-BODY
107 |
108 | ### 2015-03-28
109 |
110 | #### Features
111 |
112 | * **api**
113 | * add cool service modified (4303fd6)
114 | * add cool feature (4303fd7)
115 |
116 | * **admin**
117 | * add page to manage users (4303fd8)
118 | BODY
119 | File.open("CHANGELOG.md", "w") { |f| f.puts previous_body }
120 | body = <<-BODY
121 |
122 | ### 2015-03-30
123 |
124 | #### Features
125 |
126 | * **admin**
127 | * increase reports ranges ([4303fd4](/../../commit/4303fd4))
128 |
129 | #### Bug Fixes
130 |
131 | * **api**
132 | * fix annoying bug ([4303fd5](/../../commit/4303fd5))
133 |
134 | #{previous_body}
135 | BODY
136 | subject.generate!
137 | expect(changelog + "\n").to eql body
138 | end
139 | end
140 |
141 | context "with a version param" do
142 | let(:log) do <<-LOG
143 | 4303fd4/////2015-03-30/////feat(admin): increase reports ranges
144 | 4303fd5/////2015-03-29/////fix(api): fix annoying bug
145 | LOG
146 | end
147 |
148 | it 'preserves previous changes' do
149 | previous_body = <<-BODY
150 |
151 | ### 0.1.0 (2015-03-28)
152 |
153 | #### Features
154 |
155 | * **api**
156 | * add cool service (4303fd6)
157 | * add cool feature (4303fd7)
158 |
159 | * **admin**
160 | * add page to manage users (4303fd8)
161 | BODY
162 | File.open("CHANGELOG.md", "w") { |f| f.puts previous_body }
163 | body = <<-BODY
164 |
165 | ### 0.2.0 (2015-03-30)
166 |
167 | #### Features
168 |
169 | * **admin**
170 | * increase reports ranges ([4303fd4](/../../commit/4303fd4))
171 |
172 | #### Bug Fixes
173 |
174 | * **api**
175 | * fix annoying bug ([4303fd5](/../../commit/4303fd5))
176 |
177 | #{previous_body}
178 | BODY
179 | subject.generate! version: '0.2.0'
180 | expect(changelog + "\n").to eql body
181 | end
182 | end
183 |
184 | context "with no scope" do
185 | let(:log) do <<-LOG
186 | 4303fd4/////2015-03-30/////feat: increase reports ranges
187 | 4303fd5/////2015-03-30/////fix: fix annoying bug
188 | LOG
189 | end
190 |
191 | it 'creates changelog without scope' do
192 | subject.generate!
193 | body = <<-BODY
194 |
195 | ### 2015-03-30
196 |
197 | #### Features
198 |
199 | * increase reports ranges ([4303fd4](/../../commit/4303fd4))
200 |
201 | #### Bug Fixes
202 |
203 | * fix annoying bug ([4303fd5](/../../commit/4303fd5))
204 |
205 | BODY
206 | expect(changelog).to eql body
207 | end
208 | end
209 |
210 | end
211 |
212 | context "when the tag or date of the previous release cannot be determined from the existing CHANGELOG" do
213 | context "when the CONVENTIONAL_CHANGELOG_LAST_RELEASE environment variable is not set" do
214 | it "raises a helpful error" do
215 | File.write("CHANGELOG.md", "original")
216 | expect { subject.generate! version: "v2.0.0" }.to raise_error(ConventionalChangelog::LastReleaseNotFound, /Could not determine last tag or release date/)
217 | end
218 | end
219 |
220 | context "when the CONVENTIONAL_CHANGELOG_LAST_RELEASE environment variable is set" do
221 | before do
222 | allow(ENV).to receive(:[]).with('CONVENTIONAL_CHANGELOG_LAST_RELEASE').and_return('v1.2.3')
223 | allow(ConventionalChangelog::Git).to receive(:log).and_return log
224 | end
225 |
226 | let(:log) { "4303fd4/////2015-03-30/////feat: increase reports ranges" }
227 |
228 | it "uses the value of CONVENTIONAL_CHANGELOG_LAST_RELEASE as the last release id" do
229 | File.write("CHANGELOG.md", "original")
230 | expect(ConventionalChangelog::Git).to receive(:commits).with(since_version: 'v1.2.3').and_call_original
231 | subject.generate! version: "v2.0.0"
232 | end
233 | end
234 | end
235 |
236 | context "when an error occurs generating the commit log" do
237 | before do
238 | allow_any_instance_of(ConventionalChangelog::Writer).to receive(:append_changes).and_raise("an error")
239 | end
240 |
241 | it "maintains the original content" do
242 | File.write("CHANGELOG.md", '')
243 | expect { subject.generate! version: "v2.0.0" }.to raise_error(RuntimeError)
244 | expect(File.read("CHANGELOG.md")).to eq ''
245 | end
246 | end
247 | end
248 | end
249 |
--------------------------------------------------------------------------------