release_notes 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,161 @@
1
+
2
+
3
+ .release {
4
+ background: #EEE;
5
+ border-radius: 3px;
6
+
7
+ .note {
8
+ background-color: #fff;
9
+ border: 1px solid #CACACA;
10
+ padding: 30px;
11
+ }
12
+ }
13
+
14
+ .markdown-body {
15
+ font-size: 15px;
16
+ line-height: 1.7;
17
+ overflow: hidden;
18
+ word-wrap: break-word;
19
+
20
+ >*:first-child {
21
+ margin-top: 0 !important;
22
+ }
23
+
24
+ >*:last-child {
25
+ margin-bottom: 0 !important;
26
+ }
27
+
28
+ h1 {
29
+ font-size: 2.5em;
30
+ border-bottom: 1px solid #ddd;
31
+ }
32
+
33
+ h2 {
34
+ font-size: 2em;
35
+ border-bottom: 1px solid #eee;
36
+ }
37
+
38
+ h3 {
39
+ font-size: 1.5em;
40
+ }
41
+
42
+ h4 {
43
+ font-size: 1.2em;
44
+ }
45
+
46
+ h5 {
47
+ font-size: 1em;
48
+ }
49
+
50
+ h6 {
51
+ color: #777;
52
+ font-size: 1em;
53
+ }
54
+
55
+ h1, h2, h3, h4, h5, h6 {
56
+ margin: 1em 0 15px;
57
+ padding: 0;
58
+ font-weight: bold;
59
+ line-height: 1.7;
60
+ cursor: text;
61
+ position: relative;
62
+
63
+ .octicon-link {
64
+ display: none;
65
+ color: #000;
66
+ }
67
+ }
68
+
69
+ p, blockquote, ul, ol, dl, table, pre {
70
+ margin: 15px 0;
71
+ }
72
+
73
+ ol {
74
+ padding-left: 30px;
75
+ }
76
+
77
+ a.anchor {
78
+ display: block;
79
+ padding-right: 6px;
80
+ padding-left: 30px;
81
+ margin-left: -30px;
82
+ cursor: pointer;
83
+ position: absolute;
84
+ top: 0;
85
+ left: 0;
86
+ bottom: 0;
87
+ }
88
+
89
+ pre {
90
+ word-wrap: normal;
91
+ }
92
+
93
+ pre code, pre tt {
94
+ margin: 0;
95
+ padding: 0;
96
+ background-color: transparent;
97
+ border: none;
98
+ word-wrap: normal;
99
+ }
100
+
101
+ pre>code {
102
+ margin: 0;
103
+ padding: 0;
104
+ white-space: pre;
105
+ border: none;
106
+ background: transparent;
107
+ }
108
+
109
+ code {
110
+ white-space: nowrap;
111
+ }
112
+
113
+ code, tt {
114
+ margin: 0 2px;
115
+ padding: 0px 5px;
116
+ border: 1px solid #ddd;
117
+ background-color: #f8f8f8;
118
+ border-radius: 3px;
119
+ }
120
+
121
+ .highlight pre, pre {
122
+ background-color: #f8f8f8;
123
+ border: 1px solid #ddd;
124
+ font-size: 13px;
125
+ line-height: 19px;
126
+ overflow: auto;
127
+ padding: 6px 10px;
128
+ border-radius: 3px;
129
+ }
130
+
131
+ table {
132
+ width: 100%;
133
+ overflow: auto;
134
+ display: block;
135
+
136
+ tr {
137
+ border-top: 1px solid #ccc;
138
+ background-color: #fff;
139
+ }
140
+
141
+ tr:nth-child(2n) {
142
+ background-color: #f8f8f8;
143
+ }
144
+
145
+ th, td {
146
+ border: 1px solid #ddd;
147
+ padding: 6px 13px;
148
+ }
149
+ }
150
+
151
+ tt, code, pre {
152
+ font-family: Consolas, "Liberation Mono", Courier, monospace;
153
+ font-size: 12px;
154
+ color: #333333;
155
+ }
156
+ }
157
+
158
+ code, kbd, pre, samp {
159
+ font-family: monospace, serif;
160
+ font-size: 1em;
161
+ }
@@ -0,0 +1,2 @@
1
+ class ReleaseNotes::ApplicationController < ApplicationController
2
+ end
@@ -0,0 +1,11 @@
1
+ module ReleaseNotes
2
+ class ReleaseNotesController < ApplicationController
3
+ def index
4
+ @release_notes = "::#{ReleaseNotes.release_note_model}".constantize.all.order('-id')
5
+ end
6
+
7
+ def show
8
+ @release_notes = "::#{ReleaseNotes.release_note_model}".constantize.where(version: "#{params[:version]}".gsub('_','.'))
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,28 @@
1
+ module ReleaseNotes
2
+ module ApplicationHelper
3
+ require 'redcarpet'
4
+
5
+ def markup(markdown)
6
+ extension_options = [:no_intra_emphasis => true,
7
+ :tables => true,
8
+ :fenced_code_blocks => true,
9
+ :autolink => true,
10
+ :strikethrough => true,
11
+ :space_after_headers => true,
12
+ :superscript => true,
13
+ :underline => true,
14
+ :highlight => true,
15
+ :quote => true,
16
+ :footnotes => true]
17
+
18
+ render_options = [:filter_html => true,
19
+ :hard_wrap => true,
20
+ :prettify => true]
21
+
22
+ renderer = Redcarpet::Render::HTML.new(*render_options)
23
+ mark = Redcarpet::Markdown.new(renderer, *extension_options)
24
+
25
+ mark.render(markdown)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,40 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title><%= ReleaseNotes.app_name %> Release Notes</title>
7
+ <%= stylesheet_link_tag "release_notes/application", media: "all" %>
8
+ <%= javascript_include_tag "release_notes/bootstrap" %>
9
+ <%= csrf_meta_tags %>
10
+ <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
11
+ <!--[if lt IE 9]>
12
+ <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
13
+ <script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
14
+ <![endif]-->
15
+ </head>
16
+ <body>
17
+ <div id="wrap">
18
+ <div class="container">
19
+ <div class="header">
20
+ <ul class="nav nav-pills pull-right">
21
+ <li><%= link_to "#{ReleaseNotes.app_name}", '/' %></li>
22
+ <li <% if params[:action] == 'index' %>class="active"<% end %>><a href="/<%= ReleaseNotes.release_note_folder %>">Release Notes</a></li>
23
+ </ul>
24
+ <h3 class="text-muted"><%= ReleaseNotes.app_name %></h3>
25
+ </div>
26
+ <%= yield %>
27
+ </div>
28
+ </div>
29
+ <footer class="footer">
30
+ <div class="container">
31
+ <p class="text-muted center">
32
+ Creating using <a href="http://www.github.com/eanlain/release_notes" target="_blank">ReleaseNotes</a>.
33
+ </p>
34
+ <p class="center">
35
+ <a href="#">Back to top</a>
36
+ </p>
37
+ </div>
38
+ </footer>
39
+ </body>
40
+ </html>
@@ -0,0 +1,11 @@
1
+ <% @release_notes.each do |rn| %>
2
+ <div class="release">
3
+ <div class="row note">
4
+ <div class="col-sm-12">
5
+ <div class="markdown-body">
6
+ <%= markup(rn.markdown).html_safe %>
7
+ </div>
8
+ </div>
9
+ </div>
10
+ </div>
11
+ <% end %>
@@ -0,0 +1 @@
1
+ <%= render 'shared' %>
@@ -0,0 +1 @@
1
+ <%= render 'shared' %>
data/bin/release_notes ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ require File.expand_path('config/environment.rb')
5
+ require File.expand_path('config/initializers/release_notes.rb')
6
+ rescue LoadError
7
+ puts "Not in Rails root, or just can't find it... that's cool though - using default settings instead."
8
+ end
9
+
10
+ require 'release_notes/cli'
11
+ ReleaseNotes::CLI.start
data/config/routes.rb ADDED
@@ -0,0 +1,4 @@
1
+ ReleaseNotes::Engine.routes.draw do
2
+ get '/' => 'release_notes#index'
3
+ get '/:version' => 'release_notes#show'
4
+ end
@@ -0,0 +1 @@
1
+ require 'aruba/cucumber'
@@ -0,0 +1,47 @@
1
+ require 'rails/generators/active_record'
2
+ require 'generators/release_notes/orm_helpers'
3
+
4
+ module ActiveRecord
5
+ module Generators
6
+ class ReleaseNotesGenerator < ActiveRecord::Generators::Base
7
+ argument :attributes, :type => :array, :default => [], :banner => "field:type field:type"
8
+
9
+ include ReleaseNotes::Generators::OrmHelpers
10
+ source_root File.expand_path("../templates", __FILE__)
11
+
12
+ def copy_release_notes_migration
13
+ if (behavior == :invoke && model_exists?)
14
+ raise "#{table_name} already exists..."
15
+ else
16
+ migration_template "migration.rb", "db/migrate/release_notes_create_#{table_name}"
17
+ end
18
+ end
19
+
20
+ def generate_model
21
+ invoke "active_record:model", [name], :migration => false unless model_exists? && behavior == :invoke
22
+ end
23
+
24
+ def inject_release_notes_content
25
+ content = model_contents
26
+
27
+ class_path = if namespaced?
28
+ class_name.to_s.split("::")
29
+ else
30
+ [class_name]
31
+ end
32
+
33
+ indent_depth = class_path.size - 1
34
+ content = content.split("\n").map { |line| " " * indent_depth + line }.join("\n") << "\n"
35
+
36
+ inject_into_class(model_path, class_path.last, content) if model_exists?
37
+ end
38
+
39
+ def migration_data
40
+ <<RUBY
41
+ t.text :markdown, :null => false
42
+ t.string :version, :null => false
43
+ RUBY
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,15 @@
1
+ class ReleaseNotesCreate<%= table_name.camelize %> < ActiveRecord::Migration
2
+ def change
3
+ create_table(:<%= table_name %>) do |t|
4
+ <%= migration_data -%>
5
+
6
+ <% attributes.each do |attribute| -%>
7
+ t.<%= attribute.type %> :<%= attribute.name %>
8
+ <% end -%>
9
+
10
+ t.timestamps
11
+ end
12
+
13
+ add_index :<%= table_name %>, :version, :unique => true
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ require 'rails/generators/base'
2
+
3
+ module ReleaseNotes
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ source_root File.expand_path("../../templates", __FILE__)
7
+
8
+ desc "Creates a ReleaseNotes initializer for your application."
9
+
10
+ class_option :orm
11
+
12
+ def copy_initializer
13
+ template "release_notes.rb", "config/initializers/release_notes.rb"
14
+ end
15
+
16
+ def show_readme
17
+ readme "README" if behavior == :invoke
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,27 @@
1
+ module ReleaseNotes
2
+ module Generators
3
+ module OrmHelpers
4
+ def model_contents
5
+ buffer = <<-CONTENT
6
+ validates :version, presence: true,
7
+ uniqueness: true
8
+ CONTENT
9
+ buffer
10
+ end
11
+
12
+ private
13
+
14
+ def model_exists?
15
+ File.exists?(File.join(destination_root, model_path))
16
+ end
17
+
18
+ def migration_path
19
+ @migration_path ||= File.join("db", "migrate")
20
+ end
21
+
22
+ def model_path
23
+ @model_path ||= File.join("app", "models", "#{file_path}.rb")
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,25 @@
1
+ require 'rails/generators/named_base'
2
+
3
+ module ReleaseNotes
4
+ module Generators
5
+ class ReleaseNotesGenerator < Rails::Generators::NamedBase
6
+ include Rails::Generators::ResourceHelpers
7
+
8
+ namespace "release_notes"
9
+ source_root File.expand_path("../templates", __FILE__)
10
+
11
+ desc "Generates a model with the given NAME (if one does not exist) with " <<
12
+ "release_notes configuration plus a migration file and release_notes routes."
13
+
14
+ hook_for :orm
15
+
16
+ class_option :routes, :desc => "Generate routes", :type => :boolean, :default => true
17
+
18
+ def add_release_notes_routes
19
+ release_notes_routes = "mount ReleaseNotes::Engine, at: '/#{plural_name}'"
20
+
21
+ route release_notes_routes
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,47 @@
1
+ require 'rails/generators/base'
2
+
3
+ module ReleaseNotes
4
+ module Generators
5
+ module ViewPathTemplates
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ argument :scope, :required => false, :default => nil,
10
+ :desc => "The scope to copy views to"
11
+
12
+ public_task :copy_views
13
+ end
14
+
15
+ module ClassMethods
16
+ def hide!
17
+ Rails::Generators.hide_namespace self.namespace
18
+ end
19
+ end
20
+
21
+ protected
22
+ def view_directory(name, _target_path=nil)
23
+ directory name.to_s, _target_path || "#{target_path}/#{name}" do |content|
24
+ content
25
+ end
26
+ end
27
+
28
+ def target_path
29
+ @target_path ||= "app/views/#{scope || :release_notes}"
30
+ end
31
+ end
32
+
33
+ class ViewsGenerator < Rails::Generators::Base
34
+ include ViewPathTemplates
35
+ source_root File.expand_path("../../../../app/views/release_notes/", __FILE__)
36
+
37
+ desc "Copies ReleaseNotes views to your application."
38
+
39
+ argument :scope, :required => false, :default => nil,
40
+ :desc => "The scope to copy views to"
41
+
42
+ def copy_views
43
+ view_directory :release_notes
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,20 @@
1
+ ======================================================================================
2
+
3
+ Some setup you must do manually if you haven't yet:
4
+
5
+ 1. Check/update ReleaseNote initializer file (config/initializers/release_notes.rb).
6
+ At a minimum you may want to update the app_name... or not...
7
+
8
+ 2. Create a ReleaseNote model by running:
9
+
10
+ rails g release_notes ReleaseNote
11
+
12
+ 3. Migrate your newly created ReleaseNote model:
13
+
14
+ rake db:migrate
15
+
16
+ 4. You can copy ReleaseNotes views (for customization) to your app by running:
17
+
18
+ rails g release_notes:views
19
+
20
+ ======================================================================================
@@ -0,0 +1,14 @@
1
+ # Use this hook to configure ReleaseNotes.
2
+ ReleaseNotes.setup do |config|
3
+ # The name of your application.
4
+ config.app_name = 'Application Name Goes Here'
5
+
6
+ # The name of the model you're using to store the various release notes.
7
+ config.release_note_model = 'ReleaseNote'
8
+
9
+ # The name of the folder you're using to store the release note markdown files.
10
+ config.release_note_folder = 'release_notes'
11
+
12
+ # The version number that the first ReleaseNote should start at.
13
+ config.starting_version = '0.1.0'
14
+ end
@@ -0,0 +1,72 @@
1
+ # <%= @app_name -%> <%= @release_version.gsub('_', '.') -%> Release Notes
2
+ <% if @message['overview'].length > 0 -%>
3
+ ###### <%= @message['overview'] -%>
4
+
5
+ <% end -%>
6
+
7
+ #### <%= Time.now.utc.strftime('%m/%d/%Y') %>
8
+
9
+ <% if !@message['additions'].empty? -%>
10
+ Additions
11
+ ----
12
+ <% @message['additions'].each do |msg| -%>
13
+ * <%= msg -%>
14
+
15
+ <% end -%>
16
+ <% end -%>
17
+
18
+ <% if !@message['changes'].empty? -%>
19
+ Changes
20
+ ----
21
+ <% @message['changes'].each do |msg| -%>
22
+ * <%= msg -%>
23
+
24
+ <% end -%>
25
+ <% end -%>
26
+
27
+ <% if !@message['improvements'].empty? -%>
28
+ Improvements
29
+ ----
30
+ <% @message['improvements'].each do |msg| -%>
31
+ * <%= msg -%>
32
+
33
+ <% end -%>
34
+ <% end -%>
35
+
36
+ <% if !@message['removals'].empty? -%>
37
+ Removals
38
+ ----
39
+ <% @message['removals'].each do |msg| -%>
40
+ * <%= msg -%>
41
+
42
+ <% end -%>
43
+ <% end -%>
44
+
45
+ <% if !@message['fixes'].empty? -%>
46
+ Fixes
47
+ ----
48
+ <% @message['fixes'].each do |msg| -%>
49
+ * <%= msg -%>
50
+
51
+ <% end -%>
52
+ <% end -%>
53
+
54
+ <% if !@message['bugs'].empty? -%>
55
+ Known Issues / Bugs
56
+ ----
57
+ <% @message['bugs'].each do |msg| -%>
58
+ * <%= msg -%>
59
+
60
+ <% end -%>
61
+ <% end -%>
62
+
63
+ <% if !@message['upcoming'].empty? -%>
64
+ Upcoming
65
+ ----
66
+ <% @message['upcoming'].each do |msg| -%>
67
+ * <%= msg -%>
68
+
69
+ <% end -%>
70
+ <% end -%>
71
+
72
+ *the end*
@@ -0,0 +1,41 @@
1
+ # <%= @app_name -%> <%= @release_version.gsub('_', '.') -%> Release Notes
2
+ ###### A one (or two) sentence overview blurb of this release.
3
+
4
+ #### <%= Time.now.utc.strftime('%m/%d/%Y') %>
5
+
6
+ Additions
7
+ ----
8
+ * <em>Any new additions to the app go here.</em>
9
+
10
+
11
+ Changes
12
+ ----
13
+ * <em>Any notable changes should be covered here.</em>
14
+
15
+
16
+ Improvements
17
+ ----
18
+ * <em>Not a bad idea to highlight some improvements.</em>
19
+
20
+
21
+ Removals
22
+ ----
23
+ * <em>Something missing? ...probably should list it here.</em>
24
+
25
+
26
+ Fixes
27
+ ----
28
+ * <em>Things that were fixed since the last release.</em>
29
+
30
+
31
+ Known Issues / Bugs
32
+ ----
33
+ * <em>If any bugs are present let them be known.</em>
34
+
35
+
36
+ Upcoming
37
+ ----
38
+ * <em>What's in the release pipeline?</em>
39
+
40
+
41
+ *the end*
@@ -0,0 +1,64 @@
1
+ module ReleaseNotes
2
+ class CLI < Thor
3
+ class Helpers
4
+ class << self
5
+ include Thor::Shell
6
+
7
+ def setup_message_obj
8
+ message = {}
9
+ message['overview'] = ""
10
+ message['additions'] = []
11
+ message['changes'] = []
12
+ message['improvements'] = []
13
+ message['removals'] = []
14
+ message['fixes'] = []
15
+ message['bugs'] = []
16
+ message['upcoming'] = []
17
+ message
18
+ end
19
+
20
+ def interactive_bullets(message)
21
+ say "Enter in the letter type of bullet followed by the bullet's text (i.e. 'a: This is a simple addition bullet')", :yellow
22
+ say "Bullet types are as follows => (a)dditions, (c)hanges, (i)mprovements, (r)emovals, (f)ixes, (b)ugs/Known Issues, (u)pcoming", :yellow
23
+ say "When you are finished type 'done' to finish.", :cyan
24
+
25
+ loop do
26
+ input = ask('a/c/i/r/f/b/u: Bullet', :green)
27
+
28
+ if input == 'done' or input == "'done'"
29
+ break
30
+ elsif input == 'cancel' or input == "'cancel'"
31
+ return false
32
+ elsif input[0..2] == 'a: '
33
+ message['additions'].push input[3..input.length]
34
+ say "Addition bullet added."
35
+ elsif input[0..2] == 'c: '
36
+ message['changes'].push input[3..input.length]
37
+ say "Changes bullet added."
38
+ elsif input[0..2] == 'i: '
39
+ message['improvements'].push input[3..input.length]
40
+ say "Improvements bullet added."
41
+ elsif input[0..2] == 'r: '
42
+ message['removals'].push input[3..input.length]
43
+ say "Removals bullet added."
44
+ elsif input[0..2] == 'f: '
45
+ message['fixes'].push input[3..input.length]
46
+ say "Fixes bullet added."
47
+ elsif input[0..2] == 'b: '
48
+ message['bugs'].push input[3..input.length]
49
+ say "Bugs/Known Issues bullet added."
50
+ elsif input[0..2] == 'u: '
51
+ message['upcoming'].push input[3..input.length]
52
+ say "Upcoming bullet added."
53
+ else
54
+ say "Invalid format. Please try that last one again...", :red
55
+ end
56
+ end
57
+
58
+ message['overview'] = ask "Please give a one (or two) sentence overview of this release... or just be unhelpful and press ENTER.", :yellow
59
+ message
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end