release_notes 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +75 -0
  8. data/Rakefile +7 -0
  9. data/app/assets/javascripts/release_notes/bootstrap.js +6 -0
  10. data/app/assets/stylesheets/release_notes/application.css +75 -0
  11. data/app/assets/stylesheets/release_notes/bootstrap.css +7 -0
  12. data/app/assets/stylesheets/release_notes/github.css.scss +161 -0
  13. data/app/controllers/release_notes/application_controller.rb +2 -0
  14. data/app/controllers/release_notes/release_notes_controller.rb +11 -0
  15. data/app/helpers/release_notes/application_helper.rb +28 -0
  16. data/app/views/layouts/release_notes/application.html.erb +40 -0
  17. data/app/views/release_notes/release_notes/_shared.html.erb +11 -0
  18. data/app/views/release_notes/release_notes/index.html.erb +1 -0
  19. data/app/views/release_notes/release_notes/show.html.erb +1 -0
  20. data/bin/release_notes +11 -0
  21. data/config/routes.rb +4 -0
  22. data/features/support/setup.rb +1 -0
  23. data/lib/generators/active_record/release_notes_generator.rb +47 -0
  24. data/lib/generators/active_record/templates/migration.rb +15 -0
  25. data/lib/generators/release_notes/install_generator.rb +21 -0
  26. data/lib/generators/release_notes/orm_helpers.rb +27 -0
  27. data/lib/generators/release_notes/release_notes_generator.rb +25 -0
  28. data/lib/generators/release_notes/views_generator.rb +47 -0
  29. data/lib/generators/templates/README +20 -0
  30. data/lib/generators/templates/release_notes.rb +14 -0
  31. data/lib/generators/templates/update.md +72 -0
  32. data/lib/generators/templates/update_blank.md +41 -0
  33. data/lib/release_notes/cli/helpers.rb +64 -0
  34. data/lib/release_notes/cli.rb +135 -0
  35. data/lib/release_notes/engine.rb +5 -0
  36. data/lib/release_notes/generators/release_note.rb +78 -0
  37. data/lib/release_notes/version.rb +3 -0
  38. data/lib/release_notes/versioning/semantic.rb +50 -0
  39. data/lib/release_notes/versioning.rb +26 -0
  40. data/lib/release_notes.rb +27 -0
  41. data/release_notes.gemspec +31 -0
  42. data/spec/spec_helper.rb +17 -0
  43. metadata +200 -0
@@ -0,0 +1,135 @@
1
+ require 'thor'
2
+ require 'release_notes'
3
+ require 'release_notes/version'
4
+ require 'release_notes/versioning'
5
+ require 'release_notes/cli/helpers'
6
+ require 'release_notes/generators/release_note'
7
+
8
+ module ReleaseNotes
9
+ class CLI < Thor
10
+
11
+ package_name 'ReleaseNotes'
12
+ map '-v' => :version
13
+
14
+
15
+ desc 'new', 'create a new release note'
16
+ method_option :destination, :aliases => '-d', :default => ReleaseNotes.release_note_folder, :desc => 'relative location of release note folder'
17
+ method_option :force, :aliases => '-f', :type => :boolean, :desc => 'overwrite files that already exist'
18
+ method_option :increment, :aliases => '-i', :default => 'patch', :banner => 'MODE', :desc => 'increment version by mode'
19
+ method_option :message, :aliases => '-m', :desc => 'interactive release note bullet input'
20
+ method_option :version, :aliases => '-V', :desc => 'use the given version number'
21
+
22
+ def new
23
+ if options[:version].nil?
24
+ last_version = ReleaseNotes::Versioning.current_version_number(options[:destination])
25
+ update_version = ReleaseNotes::Versioning::Semantic.increment(last_version, options[:increment])
26
+ else
27
+ update_version = options[:version]
28
+ end
29
+
30
+ message = ReleaseNotes::CLI::Helpers.setup_message_obj
31
+
32
+ if options[:message]
33
+ message = ReleaseNotes::CLI::Helpers.interactive_bullets(message)
34
+ end
35
+
36
+ ReleaseNotes::Generators::ReleaseNote.start([options[:destination],
37
+ message,
38
+ update_version,
39
+ "--force=#{options[:force] || false}"])
40
+ end
41
+
42
+
43
+ desc 'update', "update #{ReleaseNotes.release_note_model} model"
44
+ method_option :destination, :aliases => '-d', :default => ReleaseNotes.release_note_folder, :desc => 'relative location of release note folder'
45
+ method_option :no_log, :aliases => '-n', :type => :boolean, :default => false, :desc => 'disable README.md log of release notes'
46
+ method_option :reset, :aliases => '-r', :type => :boolean, :default => false, :desc => 'delete all model entries and rebuilds them'
47
+ # method_option :version, :aliases => '-V', :desc => 'update only the given version number'
48
+
49
+ def update
50
+ # If reset option is passed delete all release notes in model
51
+ if options[:reset]
52
+ stamp = nil
53
+ release_log = ""
54
+
55
+ begin
56
+ File.delete("#{options[:destination]}/README.md")
57
+ rescue Errno::ENOENT
58
+ # Nothing to see here... move along.
59
+ end
60
+
61
+ ReleaseNotes.release_note_model.constantize.all.each do |rn|
62
+ rn.destroy
63
+ end
64
+ else
65
+ # Checks timestamp of last release note stored
66
+ begin
67
+ stamp = File.read("#{options[:destination]}/stamp")
68
+ rescue Errno::ENOENT
69
+ stamp = nil
70
+ end
71
+
72
+ # Reads contents of release note compilation file
73
+ begin
74
+ release_log = File.read("#{options[:destination]}/README.md")
75
+ rescue Errno::ENOENT
76
+ release_log = ""
77
+ end
78
+ end
79
+
80
+ # Collects relevant files and saves version and content to db
81
+ update_files = collect_update_files(options[:destination])
82
+ update_files.each do |file|
83
+ timestamp = file[0].to_i
84
+
85
+ if !stamp.nil? and timestamp <= stamp.to_i
86
+ next
87
+ end
88
+
89
+ version = file[1..4].join('.')[0..-4]
90
+
91
+ file = file.join('_')
92
+ markdown = File.read("#{options[:destination]}/#{file}")
93
+ ReleaseNotes.release_note_model.constantize.create(version: version,
94
+ markdown: markdown)
95
+
96
+ release_log.insert(0, "#{markdown}\n\n---\n\n") unless options[:no_log]
97
+ end
98
+
99
+ # Store the timestamp of the last release note
100
+ new_stamp = latest_update_file(options[:destination])
101
+ File.write("#{options[:destination]}/stamp", "#{new_stamp}", mode: 'w')
102
+
103
+ # Store release note compilation file
104
+ File.write("#{options[:destination]}/README.md", "#{release_log}", mode: 'w') unless options[:no_log]
105
+
106
+ say "#{ReleaseNotes.release_note_model} model successfully updated.", :green
107
+ say "ReleaseNotes log successfully updated (see #{options[:destination]}/README.md).", :green unless options[:no_log]
108
+ end
109
+
110
+
111
+ desc 'version', 'show version of release_notes'
112
+
113
+ def version
114
+ puts "ReleaseNotes #{ReleaseNotes::VERSION}"
115
+ end
116
+
117
+
118
+ protected
119
+ def collect_update_files(dirname)
120
+ update_lookup_at(dirname).collect do |file|
121
+ File.basename(file).split('_')
122
+ end
123
+ end
124
+
125
+ def latest_update_file(dirname)
126
+ update_lookup_at(dirname).collect do |file|
127
+ File.basename(file).split('_').first.to_i
128
+ end.max.to_i
129
+ end
130
+
131
+ def update_lookup_at(dirname)
132
+ Dir.glob("#{dirname}/[0-9]*_*.md")
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,5 @@
1
+ module ReleaseNotes
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace ReleaseNotes
4
+ end
5
+ end
@@ -0,0 +1,78 @@
1
+ require 'thor/group'
2
+
3
+ module ReleaseNotes
4
+ module Generators
5
+ class ReleaseNote < Thor::Group
6
+ include Thor::Actions
7
+
8
+ argument :destination, :type => :string
9
+ argument :message, :type => :hash
10
+ argument :release_version, :type => :string
11
+
12
+ class_option :force, :type => :boolean, :default => false
13
+
14
+ source_root File.expand_path('../../../generators/templates', __FILE__)
15
+
16
+ def set_local_assigns
17
+ @app_name = ReleaseNotes.app_name
18
+ @update_template = 'update_blank.md'
19
+ @destination = File.expand_path(destination)
20
+ @release_version = release_version.gsub('.', '_')
21
+ @message = message
22
+
23
+ message.each do |k,v|
24
+ if v.length > 0
25
+ @update_template = 'update.md'
26
+ break
27
+ end
28
+ end
29
+ end
30
+
31
+ def create_update_file
32
+ empty_directory(@destination)
33
+ end
34
+
35
+ def check_version
36
+ destination = version_exists?(@destination, @release_version)
37
+
38
+ if destination
39
+ if options.force?
40
+ remove_file(destination)
41
+ else
42
+ raise Thor::Error,
43
+ <<-ERROR
44
+ Another update was found using the version number #{@release_version.gsub('_', '.')}.
45
+ Use --force to remove the old update file and replace it.
46
+ ERROR
47
+ end
48
+ end
49
+ end
50
+
51
+ def copy_release_note
52
+ update_number = next_update_number(destination)
53
+ @filename = "#{destination}/#{update_number}_#{@release_version}.md"
54
+ template(@update_template, @filename)
55
+ end
56
+
57
+ protected
58
+ def next_update_number(dirname)
59
+ next_update_number = current_update_number(dirname) + 1
60
+ [Time.now.utc.strftime('%Y%m%d%H%M%S'), '%.14d' % next_update_number].max
61
+ end
62
+
63
+ def current_update_number(dirname)
64
+ update_lookup_at(dirname).collect do |file|
65
+ File.basename(file).split('_').first.to_i
66
+ end.max.to_i
67
+ end
68
+
69
+ def update_lookup_at(dirname)
70
+ Dir.glob("#{dirname}/[0-9]*_*.md")
71
+ end
72
+
73
+ def version_exists?(dirname, file_name)
74
+ update_lookup_at(dirname).grep(/\d+_#{file_name}.md$/).first
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,3 @@
1
+ module ReleaseNotes
2
+ VERSION = "0.1.3"
3
+ end
@@ -0,0 +1,50 @@
1
+ module ReleaseNotes
2
+ module Versioning
3
+ module Semantic
4
+ class << self
5
+
6
+ def increment(version, type)
7
+ if version.nil?
8
+ ReleaseNotes.starting_version
9
+ else
10
+ parts = parse_version(version.gsub('.md', ''))
11
+
12
+ if type.downcase == 'major' or type == 'M'
13
+ parts = increment_major(parts)
14
+ elsif type.downcase == 'minor' or type == 'm'
15
+ parts = increment_minor(parts)
16
+ else
17
+ parts = increment_patch(parts)
18
+ end
19
+
20
+ new_version = parts.join('.')
21
+ new_version
22
+ end
23
+ end
24
+
25
+ protected
26
+ def parse_version(version)
27
+ version.split('-').first.split('.')
28
+ end
29
+
30
+ def increment_major(parts)
31
+ parts[0] = (parts[0].to_i + 1).to_s
32
+ parts[1] = '0'
33
+ parts[2] = '0'
34
+ parts
35
+ end
36
+
37
+ def increment_minor(parts)
38
+ parts[1] = (parts[1].to_i + 1).to_s
39
+ parts[2] = '0'
40
+ parts
41
+ end
42
+
43
+ def increment_patch(parts)
44
+ parts[2] = (parts[2].to_i + 1).to_s
45
+ parts
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,26 @@
1
+ require 'release_notes/versioning/semantic'
2
+
3
+ module ReleaseNotes
4
+ module Versioning
5
+ class << self
6
+ def current_version_number(dirname)
7
+ last_timestamp = version_lookup_at(dirname).collect do |file|
8
+ File.basename(file).split("_").first.to_i
9
+ end.max.to_i
10
+
11
+ last_version = Dir.glob("#{dirname}/#{last_timestamp}_*").to_s.split('/').last
12
+ last_version = last_version.gsub(last_version[0..14], '')[0..-3].gsub('_', '.')
13
+
14
+ if last_version.empty?
15
+ return nil
16
+ else
17
+ return last_version
18
+ end
19
+ end
20
+
21
+ def version_lookup_at(dirname)
22
+ Dir.glob("#{dirname}/[0-9]*_*")
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,27 @@
1
+ require 'rails'
2
+
3
+ module ReleaseNotes
4
+ # Name of application using ReleaseNotes.
5
+ mattr_accessor :app_name
6
+ @@app_name = 'AppNameGoesHere'
7
+
8
+ # Version to start ReleaseNotes if there are none.
9
+ mattr_accessor :starting_version
10
+ @@starting_version = '0.1.0'
11
+
12
+ # Model name of the model created to store release notes.
13
+ mattr_accessor :release_note_model
14
+ @@release_note_model = 'ReleaseNote'
15
+
16
+ # Name of the folder where release notes are stored.
17
+ mattr_accessor :release_note_folder
18
+ @@release_note_folder = 'release_notes'
19
+
20
+ # Default way to setup ReleaseNotes. Run rails g release_notes:install
21
+ # to create a fresh initializer with all configuration values.
22
+ def self.setup
23
+ yield self
24
+ end
25
+ end
26
+
27
+ require 'release_notes/engine'
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'release_notes/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "release_notes"
8
+ spec.version = ReleaseNotes::VERSION
9
+ spec.authors = ["Brandon Robins"]
10
+ spec.email = ["brandon@ourlabel.com"]
11
+ spec.summary = "An easy way to incorporate and manage release notes."
12
+ spec.description = "An easy way to incorporate and manage release notes."
13
+ spec.homepage = "http://www.github.com/eanlain/release_notes"
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.executables << 'release_notes'
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.5"
23
+ spec.add_development_dependency "rake", "~> 10.1.1"
24
+ spec.add_development_dependency "rspec", "~> 2.14"
25
+ spec.add_development_dependency "cucumber", "~> 1.3.10"
26
+ spec.add_development_dependency "aruba", "~> 0.5.4"
27
+
28
+ spec.add_dependency "thor", "~> 0.18.1"
29
+ spec.add_dependency "rails", "~> 4.0.0"
30
+ spec.add_dependency "redcarpet", "~> 3.0.0"
31
+ end
@@ -0,0 +1,17 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+
12
+ # Run specs in random order to surface order dependencies. If you find an
13
+ # order dependency and want to debug it, you can fix the order by providing
14
+ # the seed, which is printed after each run.
15
+ # --seed 1234
16
+ config.order = 'random'
17
+ end
metadata ADDED
@@ -0,0 +1,200 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: release_notes
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.3
5
+ platform: ruby
6
+ authors:
7
+ - Brandon Robins
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-01-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 10.1.1
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 10.1.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '2.14'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '2.14'
55
+ - !ruby/object:Gem::Dependency
56
+ name: cucumber
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 1.3.10
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 1.3.10
69
+ - !ruby/object:Gem::Dependency
70
+ name: aruba
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: 0.5.4
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: 0.5.4
83
+ - !ruby/object:Gem::Dependency
84
+ name: thor
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: 0.18.1
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: 0.18.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: rails
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: 4.0.0
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: 4.0.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: redcarpet
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: 3.0.0
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ~>
123
+ - !ruby/object:Gem::Version
124
+ version: 3.0.0
125
+ description: An easy way to incorporate and manage release notes.
126
+ email:
127
+ - brandon@ourlabel.com
128
+ executables:
129
+ - release_notes
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - .gitignore
134
+ - .rspec
135
+ - .ruby-version
136
+ - Gemfile
137
+ - LICENSE.txt
138
+ - README.md
139
+ - Rakefile
140
+ - app/assets/javascripts/release_notes/bootstrap.js
141
+ - app/assets/stylesheets/release_notes/application.css
142
+ - app/assets/stylesheets/release_notes/bootstrap.css
143
+ - app/assets/stylesheets/release_notes/github.css.scss
144
+ - app/controllers/release_notes/application_controller.rb
145
+ - app/controllers/release_notes/release_notes_controller.rb
146
+ - app/helpers/release_notes/application_helper.rb
147
+ - app/views/layouts/release_notes/application.html.erb
148
+ - app/views/release_notes/release_notes/_shared.html.erb
149
+ - app/views/release_notes/release_notes/index.html.erb
150
+ - app/views/release_notes/release_notes/show.html.erb
151
+ - bin/release_notes
152
+ - config/routes.rb
153
+ - features/support/setup.rb
154
+ - lib/generators/active_record/release_notes_generator.rb
155
+ - lib/generators/active_record/templates/migration.rb
156
+ - lib/generators/release_notes/install_generator.rb
157
+ - lib/generators/release_notes/orm_helpers.rb
158
+ - lib/generators/release_notes/release_notes_generator.rb
159
+ - lib/generators/release_notes/views_generator.rb
160
+ - lib/generators/templates/README
161
+ - lib/generators/templates/release_notes.rb
162
+ - lib/generators/templates/update.md
163
+ - lib/generators/templates/update_blank.md
164
+ - lib/release_notes.rb
165
+ - lib/release_notes/cli.rb
166
+ - lib/release_notes/cli/helpers.rb
167
+ - lib/release_notes/engine.rb
168
+ - lib/release_notes/generators/release_note.rb
169
+ - lib/release_notes/version.rb
170
+ - lib/release_notes/versioning.rb
171
+ - lib/release_notes/versioning/semantic.rb
172
+ - release_notes.gemspec
173
+ - spec/spec_helper.rb
174
+ homepage: http://www.github.com/eanlain/release_notes
175
+ licenses:
176
+ - MIT
177
+ metadata: {}
178
+ post_install_message:
179
+ rdoc_options: []
180
+ require_paths:
181
+ - lib
182
+ required_ruby_version: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - '>='
185
+ - !ruby/object:Gem::Version
186
+ version: '0'
187
+ required_rubygems_version: !ruby/object:Gem::Requirement
188
+ requirements:
189
+ - - '>='
190
+ - !ruby/object:Gem::Version
191
+ version: '0'
192
+ requirements: []
193
+ rubyforge_project:
194
+ rubygems_version: 2.2.1
195
+ signing_key:
196
+ specification_version: 4
197
+ summary: An easy way to incorporate and manage release notes.
198
+ test_files:
199
+ - features/support/setup.rb
200
+ - spec/spec_helper.rb