stove 1.1.2 → 2.0.0.beta.1

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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -2
  3. data/CHANGELOG.md +16 -0
  4. data/README.md +41 -29
  5. data/Rakefile +15 -0
  6. data/bin/bake +1 -2
  7. data/features/actions/bump.feature +22 -0
  8. data/features/actions/changelog.feature +45 -0
  9. data/features/actions/dev.feature +18 -0
  10. data/features/actions/upload.feature +48 -0
  11. data/features/plugins/git.feature +24 -0
  12. data/features/rake.feature +1 -2
  13. data/features/step_definitions/cli_steps.rb +1 -27
  14. data/features/step_definitions/{community_site_steps.rb → community_steps.rb} +9 -5
  15. data/features/step_definitions/config_steps.rb +24 -0
  16. data/features/step_definitions/cookbook_steps.rb +28 -6
  17. data/features/step_definitions/cucumber_steps.rb +12 -0
  18. data/features/step_definitions/git_steps.rb +10 -7
  19. data/features/support/env.rb +12 -28
  20. data/features/support/stove/git.rb +48 -0
  21. data/lib/stove.rb +102 -19
  22. data/lib/stove/actions/base.rb +21 -0
  23. data/lib/stove/actions/bump.rb +25 -0
  24. data/lib/stove/actions/changelog.rb +71 -0
  25. data/lib/stove/actions/dev.rb +22 -0
  26. data/lib/stove/actions/finish.rb +8 -0
  27. data/lib/stove/actions/start.rb +7 -0
  28. data/lib/stove/actions/upload.rb +27 -0
  29. data/lib/stove/cli.rb +107 -79
  30. data/lib/stove/community.rb +124 -0
  31. data/lib/stove/config.rb +62 -13
  32. data/lib/stove/cookbook.rb +76 -238
  33. data/lib/stove/cookbook/metadata.rb +16 -11
  34. data/lib/stove/error.rb +13 -107
  35. data/lib/stove/filter.rb +59 -0
  36. data/lib/stove/jira.rb +74 -30
  37. data/lib/stove/middlewares/chef_authentication.rb +60 -0
  38. data/lib/stove/middlewares/exceptions.rb +17 -0
  39. data/lib/stove/mixins/filterable.rb +11 -0
  40. data/lib/stove/mixins/insideable.rb +13 -0
  41. data/lib/stove/mixins/instanceable.rb +23 -0
  42. data/lib/stove/mixins/loggable.rb +32 -0
  43. data/lib/stove/mixins/optionable.rb +41 -0
  44. data/lib/stove/mixins/validatable.rb +7 -0
  45. data/lib/stove/packager.rb +23 -22
  46. data/lib/stove/plugins/base.rb +35 -0
  47. data/lib/stove/plugins/git.rb +71 -0
  48. data/lib/stove/plugins/github.rb +108 -0
  49. data/lib/stove/plugins/jira.rb +72 -0
  50. data/lib/stove/rake_task.rb +56 -37
  51. data/lib/stove/runner.rb +84 -0
  52. data/lib/stove/util.rb +56 -0
  53. data/lib/stove/validator.rb +67 -0
  54. data/lib/stove/version.rb +1 -1
  55. data/locales/en.yml +231 -0
  56. data/stove.gemspec +11 -11
  57. metadata +85 -67
  58. data/features/changelog.feature +0 -22
  59. data/features/cli.feature +0 -11
  60. data/features/devodd.feature +0 -19
  61. data/features/git.feature +0 -34
  62. data/features/upload.feature +0 -40
  63. data/lib/stove/community_site.rb +0 -85
  64. data/lib/stove/formatter.rb +0 -7
  65. data/lib/stove/formatter/base.rb +0 -32
  66. data/lib/stove/formatter/human.rb +0 -9
  67. data/lib/stove/formatter/silent.rb +0 -10
  68. data/lib/stove/git.rb +0 -82
  69. data/lib/stove/github.rb +0 -43
  70. data/lib/stove/logger.rb +0 -56
  71. data/lib/stove/uploader.rb +0 -64
  72. data/spec/support/community_site.rb +0 -33
  73. data/spec/support/git.rb +0 -52
@@ -1,63 +1,82 @@
1
1
  require 'rake'
2
2
  require 'rake/tasklib'
3
+ require 'stove'
3
4
 
5
+ #
6
+ # @todo Most of these options are duplicated from the CLI, can we unify?
7
+ #
4
8
  module Stove
5
- #
6
- # Run Stove tasks from your +Rakefile+.
7
- #
8
- # @example
9
- # desc "Run stove tasks"
10
- # Stove::RakeTask.new(:release) do |stove|
11
- # stove.git = true
12
- # stove.devodd = true
13
- # end
14
- #
15
- class RakeTask < ::Rake::TaskLib
9
+ class RakeTask < Rake::TaskLib
10
+ include Mixin::Loggable
11
+
16
12
  class << self
17
13
  #
18
14
  # Define a CLI option.
19
15
  #
20
16
  # @param [Symbol] option
21
17
  #
22
- def cli_option(option)
18
+ def option(option)
23
19
  define_method("#{option}=".to_sym) do |value|
24
- options[option] = value
25
- end
26
-
27
- define_method(option.to_sym) do
28
- options[option]
20
+ log.debug("Setting #{option} = #{value.inspect}")
21
+ options[option.to_sym] = value
29
22
  end
30
23
  end
31
24
  end
32
25
 
33
- # @return [Symbol]
34
- attr_accessor :name
26
+ # Actions
27
+ Action.constants.map(&Action.method(:const_get)).select(&:id).each do |action|
28
+ option action.id
29
+ end
35
30
 
36
- # @return [Hash]
37
- attr_reader :options
31
+ # Plugins
32
+ Plugin.constants.map(&Plugin.method(:const_get)).select(&:id).each do |plugin|
33
+ option plugin.id
34
+ end
38
35
 
39
- def initialize(task_name = nil)
40
- @options = {}
41
- @name = (task_name || :publish).to_sym
36
+ option :category
37
+ option :path
38
+ option :remote
39
+ option :branch
42
40
 
41
+ def initialize(name = nil)
43
42
  yield self if block_given?
44
43
 
45
44
  desc 'Publish this cookbook' unless ::Rake.application.last_comment
46
- task name do |t, args|
47
- require 'stove'
48
- Stove::Cookbook.new(options).release!
45
+ task(name || :publish, :version) do |t, args|
46
+ log.info("Options: #{options.inspect}")
47
+
48
+ cookbook = Cookbook.new(options[:path])
49
+ options[:version] = args[:version] || minor_bump(cookbook.version)
50
+ Runner.run(cookbook, options)
49
51
  end
50
52
  end
51
53
 
52
- cli_option :branch
53
- cli_option :category
54
- cli_option :changelog
55
- cli_option :devodd
56
- cli_option :git
57
- cli_option :jira
58
- cli_option :log_level
59
- cli_option :path
60
- cli_option :remote
61
- cli_option :upload
54
+ def locale=(locale)
55
+ log.debug("Setting locale = #{locale.inspect}")
56
+ I18n.locale = locale
57
+ end
58
+
59
+ def log_level=(level)
60
+ log.debug("Setting log_level = #{level.inspect}")
61
+ Stove.log_level = level
62
+ end
63
+
64
+ private
65
+
66
+ def minor_bump(version)
67
+ split = version.split('.').map(&:to_i)
68
+ split[2] += 1
69
+ split.join('.')
70
+ end
71
+
72
+ def options
73
+ @options ||= Hash.new(true).tap do |h|
74
+ h[:path] = Dir.pwd
75
+ h[:jira] = false
76
+
77
+ h[:remote] = 'origin'
78
+ h[:branch] = 'master'
79
+ end
80
+ end
62
81
  end
63
82
  end
@@ -0,0 +1,84 @@
1
+ module Stove
2
+ class Runner
3
+ include Mixin::Instanceable
4
+ include Mixin::Loggable
5
+ include Mixin::Optionable
6
+
7
+ class << self
8
+ def action(id)
9
+ actions << id
10
+ filters[id] = { before: [], after: [] }
11
+ end
12
+ end
13
+
14
+ attr_reader :cookbook
15
+ attr_reader :options
16
+ attr_reader :validations
17
+
18
+ option :actions, []
19
+ option :filters, {}
20
+
21
+ action :start
22
+ action :bump
23
+ action :changelog
24
+ action :upload
25
+ action :dev
26
+ action :finish
27
+
28
+ def initialize
29
+ @validations = []
30
+ end
31
+
32
+ def run(cookbook, options = {})
33
+ @cookbook, @options = cookbook, options
34
+
35
+ run_validations
36
+ run_actions
37
+ end
38
+
39
+ private
40
+
41
+ def skip?(thing)
42
+ !options[thing.to_sym]
43
+ end
44
+
45
+ def run_actions
46
+ actions.each do |action|
47
+ if skip?(action)
48
+ log.debug("Skipping action `#{action}' and filters")
49
+ else
50
+ run_filters(:before, action)
51
+
52
+ klass = Action.const_get(Util.camelize(action))
53
+ klass.new(cookbook, options).run
54
+
55
+ run_filters(:after, action)
56
+ end
57
+ end
58
+ end
59
+
60
+ def run_filters(placement, action)
61
+ filters[action][placement].each do |filter|
62
+ plugin = filter.klass.id
63
+
64
+ if skip?(plugin)
65
+ log.debug("Skipping filter `#{filter.message}'")
66
+ else
67
+ filter.run(cookbook, options)
68
+ end
69
+ end
70
+ end
71
+
72
+ def run_validations
73
+ validations.each do |validation|
74
+ parent = validation.klass.id
75
+
76
+ if skip?(parent)
77
+ log.debug("Skipping validation `#{validation.id}' for `#{parent}'")
78
+ else
79
+ validation.run(cookbook, options)
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
data/lib/stove/util.rb ADDED
@@ -0,0 +1,56 @@
1
+ module Stove
2
+ module Util
3
+ extend self
4
+
5
+ # Convert a version string (x.y.z) to a community-site friendly format
6
+ # (x_y_z).
7
+ #
8
+ # @example Convert a version to a version string
9
+ # format_version('1.2.3') #=> 1_2_3
10
+ #
11
+ # @param [#to_s] version
12
+ # the version string to convert
13
+ #
14
+ # @return [String]
15
+ def version_for_url(version)
16
+ version
17
+ .to_s
18
+ .gsub('.', '_')
19
+ end
20
+
21
+ #
22
+ # Covert the given CaMelCaSeD string to under_score. Graciously borrowed
23
+ # from http://stackoverflow.com/questions/1509915.
24
+ #
25
+ # @param [String] string
26
+ # the string to use for transformation
27
+ #
28
+ # @return [String]
29
+ #
30
+ def underscore(string)
31
+ string
32
+ .to_s
33
+ .gsub(/::/, '/')
34
+ .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
35
+ .gsub(/([a-z\d])([A-Z])/,'\1_\2')
36
+ .tr('-', '_')
37
+ .downcase
38
+ end
39
+
40
+ #
41
+ # Convert an underscored string to it's camelcase equivalent constant.
42
+ #
43
+ # @param [String]
44
+ # the string to convert
45
+ #
46
+ # @return [String]
47
+ #
48
+ def camelize(string)
49
+ string
50
+ .to_s
51
+ .split('_')
52
+ .map { |e| e.capitalize }
53
+ .join
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,67 @@
1
+ module Stove
2
+ class Validator
3
+ include Mixin::Insideable
4
+ include Mixin::Loggable
5
+
6
+ #
7
+ # The class that created this validator.
8
+ #
9
+ # @return [~Class]
10
+ #
11
+ attr_reader :klass
12
+
13
+ #
14
+ # The identifier or field this validator runs against.
15
+ #
16
+ # @return [Symbol]
17
+ #
18
+ attr_reader :id
19
+
20
+ #
21
+ # The block to execute to see if the validation passes.
22
+ #
23
+ # @return [Proc]
24
+ #
25
+ attr_reader :block
26
+
27
+ #
28
+ # Create a new validator object.
29
+ #
30
+ # @param [~Class] klass
31
+ # the class that created this validator
32
+ # @param [Symbol] id
33
+ # the identifier or field this validator runs against
34
+ # @param [Proc] block
35
+ # the block to execute to see if the validation passes
36
+ #
37
+ def initialize(klass, id, &block)
38
+ @klass = klass
39
+ @id = id
40
+ @block = block
41
+ end
42
+
43
+ #
44
+ # Execute this validation in the context of the creating class, inside the
45
+ # given cookbook's path.
46
+ #
47
+ # @param [Cookbook]
48
+ # the cookbook to run this validation against
49
+ #
50
+ def run(cookbook, options = {})
51
+ log.info("Running validations for #{klass.id}.#{id}")
52
+
53
+ inside(cookbook) do
54
+ instance = klass.new(cookbook, options)
55
+ unless result = instance.instance_eval(&block)
56
+ log.debug("Validation failed, result: #{result.inspect}")
57
+ raise Error::ValidationFailed.new(klass.id, id,
58
+ path: Dir.pwd,
59
+ result: result,
60
+ )
61
+ end
62
+ end
63
+
64
+ log.debug("Validation #{id} passed!")
65
+ end
66
+ end
67
+ end
data/lib/stove/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Stove
2
- VERSION = '1.1.2'
2
+ VERSION = '2.0.0.beta.1'
3
3
  end
data/locales/en.yml ADDED
@@ -0,0 +1,231 @@
1
+ en:
2
+ stove:
3
+ errors:
4
+ abstract_method: >
5
+ `%{method}` is an abstract method. You must override this method in
6
+ your subclass with the proper implementation and logic. For more
7
+ information, please see the inline documentation for %{method}. If you
8
+ are not a developer, this is most likely a bug. Please file a bug report
9
+ at https://github.com/sethvargo/stove/issues/new and include the
10
+ command(s) you ran to arrive at this error.
11
+
12
+ git_failed: >
13
+ An error occurred while running:
14
+
15
+ git %{command}
16
+
17
+ There is likely an informative message from git that explains what
18
+ happened right above this message.
19
+
20
+ metadata_not_found: >
21
+ The file at `%{path}' does not exist or does not contain valid metadata.
22
+ Please make sure you have specified the correct path and that the
23
+ metdata file exists.
24
+
25
+ server_unavailable: >
26
+ The server at `%{url}` is unavailable or is not currently accepting
27
+ client connections. Please ensure the server is accessible via ping (or
28
+ telnet) on your local network. If this error persists, please contact
29
+ your network administrator.
30
+
31
+
32
+ validations:
33
+ # Bump validations
34
+ # ----------------
35
+ bump:
36
+ changed: >
37
+ The version you are trying to bump already exists! You must specify a
38
+ new version.
39
+
40
+ incremented: >
41
+ The cookbook version you are attempting to bump to is less than the
42
+ existing version. You cannot (re-)release a previous version of the
43
+ same cookbook. Please specify a higher version.
44
+
45
+
46
+ # Changelog validations
47
+ # ---------------------
48
+ changelog:
49
+ editor: >
50
+ The `$EDITOR' environment variable is not set. In order to use the
51
+ Changelog plugin, you must set a default editor for Stove to open when
52
+ generating the CHANGLEOG. You can set the editor like this:
53
+
54
+ export EDITOR=vi
55
+
56
+ exists: >
57
+ There is no `CHANGELOG.md' found at `%{path}. In order to use the
58
+ Changelog plugin, you must have a changelog in markdown format at the
59
+ root of your cookbook. You can also skip the Changelog plugin by
60
+ specifying the `--no-changelog' option:
61
+
62
+ bake x.y.z --no-changelog
63
+
64
+ format: >
65
+ The changelog at `%{path}' does not appear to be a valid format. The
66
+ changelog must be in the following format:
67
+
68
+ [Cookbook Name]
69
+ ===============
70
+
71
+ v[version] ([release date])
72
+ ---------------------------
73
+ - [Release point]
74
+
75
+ For example:
76
+
77
+ Apache 2
78
+ ========
79
+
80
+ v1.0.0 (2013-04-05)
81
+ -------------------
82
+ - Initial release
83
+
84
+
85
+ # Git validations
86
+ # ---------------
87
+ git:
88
+ clean: >
89
+ The cookbook at `%{path}' has untracked files! In order to use the git
90
+ plugin, you must have a clean working directory. Please commit or
91
+ stash your changes before running Stove again.
92
+
93
+ repository: >
94
+ The cookbook at `%{path}' does not appear to be a valid git
95
+ repository. In order to use the git plugin, your cookbook must be
96
+ initialized as a git repository. To create a git repository, run:
97
+
98
+ git init %{path}
99
+
100
+ up_to_date: >
101
+ The cookbook at `%{path}' is out of sync with the remote repository.
102
+ Please update your local cache with the remote repository before
103
+ continuing:
104
+
105
+ git pull
106
+
107
+ And then push your local changes to the remote repository:
108
+
109
+ git push
110
+
111
+
112
+ # GitHub validations
113
+ # ------------------
114
+ github:
115
+ access_token: >
116
+ The Stove configuration for GitHub does not contain an access token.
117
+ In order to use the GitHub plugin, you must set an access token in the
118
+ GitHub section of the `~/.stove' file:
119
+
120
+ {
121
+ "github": {
122
+ "access_token": "YOUR_ACCESS_TOKEN"
123
+ }
124
+ }
125
+
126
+ You can generate an access token for GitHub by following the
127
+ instructions at: https://help.github.com/articles/creating-an-access-token-for-command-line-use.
128
+
129
+ configuration: >
130
+ The Stove configuration for GitHub does not exist! In order to use the
131
+ GitHub plugin, you must set your GitHub information in the `~/.stove'
132
+ file:
133
+
134
+ {
135
+ "github": {
136
+ "access_token": "YOUR_ACCESS_TOKEN"
137
+ }
138
+ }
139
+
140
+ git: >
141
+ In order to use the GitHub plugin, you must also activate the `git'
142
+ plugin.
143
+
144
+
145
+ # JIRA validations
146
+ # ----------------
147
+ jira:
148
+ configuration: >
149
+ The Stove configuration for JIRA does not exist! In order to use the
150
+ JIRA plugin, you must set your JIRA information in the `~/.stove'
151
+ file:
152
+
153
+ {
154
+ "jira": {
155
+ "username": "YOUR_USERNAME",
156
+ "password": "YOUR_PASSWORD"
157
+ }
158
+ }
159
+
160
+ password: >
161
+ The Stove configuration for JIRA does not contain a password. In order
162
+ to use JIRA features, you must set a password in the jira section of
163
+ the `~/.stove' file:
164
+
165
+ {
166
+ "jira": {
167
+ "password": "YOUR_PASSWORD"
168
+ }
169
+ }
170
+
171
+ username: >
172
+ The Stove configuration for JIRA does not contain a username. In order
173
+ to use JIRA features, you must set a username in the jira section of
174
+ the `~/.stove' file:
175
+
176
+ {
177
+ "jira": {
178
+ "username": "YOUR_USERNAME"
179
+ }
180
+ }
181
+
182
+
183
+ # Upload validations
184
+ # ---------------------
185
+ upload:
186
+ configuration: >
187
+ The Stove configuration for the Chef community site does not exist! In
188
+ order to perform operations against the Chef community site, you must
189
+ set your username and path to your client key in the community section
190
+ of the `~/.stove' file:
191
+
192
+ {
193
+ "community": {
194
+ "username": "YOUR_USERNAME",
195
+ "key": "YOUR_KEY_PATH"
196
+ }
197
+ }
198
+
199
+ key: >
200
+ The Stove configuration for the Chef community site does not contain a
201
+ key. In order to use the Chef community site features, you must set
202
+ the path to your key the community section of the `~/.stove' file:
203
+
204
+ {
205
+ "community": {
206
+ "key": "YOUR_KEY_PATH"
207
+ }
208
+ }
209
+
210
+ username: >
211
+ The Stove configuration for the Chef community site does not contain a
212
+ username. In order to use the Chef community site features, you must
213
+ set a username the community section of the `~/.stove' file:
214
+
215
+ {
216
+ "community": {
217
+ "username": "YOUR_USERNAME"
218
+ }
219
+ }
220
+
221
+ category: >
222
+ You did not specify a category! The Chef community site requires all
223
+ cookbooks belong to a category. For existing cookboks, Stove can query
224
+ the Chef community site API and automatically complete the category
225
+ for you. However, for new cookbooks, you must specify the `--category'
226
+ flag at runtime:
227
+
228
+ bake x.y.z --category Utilities
229
+
230
+ For a complete listing of categories, please see the Chef community
231
+ site.