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,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