├── 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 | [![Build Status](https://travis-ci.org/dcrec1/conventional-changelog-ruby.svg?branch=master)](https://travis-ci.org/dcrec1/conventional-changelog-ruby) 2 | [![Code Climate](https://codeclimate.com/github/dcrec1/conventional-changelog-ruby/badges/gpa.svg)](https://codeclimate.com/github/dcrec1/conventional-changelog-ruby) 3 | [![Test Coverage](https://codeclimate.com/github/dcrec1/conventional-changelog-ruby/badges/coverage.svg)](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 | --------------------------------------------------------------------------------