knife-community 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
19
+
20
+ Gemfile.lock
21
+ .rvmrc
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
5
+ env:
6
+ - CHEF_VERSION=0.10.8
7
+ - CHEF_VERSION=10.12.0
8
+ - CHEF_VERSION=10.14.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in knife-community.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,14 @@
1
+ # A Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+ end
9
+
10
+ guard 'cucumber' do
11
+ watch(%r{^features/.+\.feature$})
12
+ watch(%r{^features/support/.+$}) { 'features' }
13
+ watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
14
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Mike Fiedler
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.
data/README.md ADDED
@@ -0,0 +1,93 @@
1
+ knife-community
2
+ ===============
3
+ [![Build Status](https://secure.travis-ci.org/miketheman/knife-community.png?branch=master)](http://travis-ci.org/miketheman/knife-community)
4
+ [![Dependency Status](https://gemnasium.com/miketheman/knife-community.png)](https://gemnasium.com/miketheman/knife-community)
5
+
6
+ A Knife plugin to assist with deploying completed Chef cookbooks to the Community Site
7
+
8
+ Intro
9
+ -----
10
+
11
+ There are sooo many ways to [deliver software][wiki:apppkg].
12
+ Apt has 'deb', Yum has 'rpm', Node has 'npm', RubyGems has 'gem', Java has 'jar', etc etc etc.
13
+
14
+ In The Land of [Chef][chef], the typical unit of shareable software is a 'cookbook'.
15
+
16
+ The centralized location for sharing cookbooks is the [Community Site][opcs], and we already have support to download/install these elements, either it be through [knife itself][kcsi], [librarian][libr], and [berkshelf][brks], and there are probably others.
17
+
18
+ What we _don't_ have is a good method for cookbook maintainers to contribute back to the Community Site, while semi-enforcing good habits, such as version incrementing, git tags and forming the package correctly.
19
+
20
+ Assumptions
21
+ -----------
22
+
23
+ ### Basics
24
+ * You know what Git is
25
+ * You know what Chef is
26
+ * You have Push permissions to the remote GitHub repository
27
+ * You don't already have a perfected workflow that works for you
28
+ * You want to be a helpful citizen of the community
29
+
30
+ ### Important
31
+ * You have **not** incremented the version number in `metadata.rb` - this will do so for you
32
+ * You have a `name` string defined in your `metadata.rb`, OR your repository name is identical to your cookbook name
33
+ * You have either committed or staged all changes to be included with this version release. Any uncommitted changed should be `git stash`ed, or stage them to be committed along with the version via `git add`
34
+
35
+ Cookbook Release Workflow
36
+ -------------------------
37
+
38
+ Assuming you have made your changes, tested your code thoroughly (one can hope!), all merged into your `master` branch, and are ready to release a new version of your cookbook, here's a flow to follow:
39
+
40
+ 1. Ensure that the branch is ready to be committed. If there are uncommitted changes, error out.
41
+ 1. Read in the current `metadata.rb`, inspect the `version` string, and increment it to the next tiny version. Override with CLI argument.
42
+ 1. Create a git commit for the `metadata.rb` change.
43
+ 1. Create a git tag with the version number (no leading "v" or the like)
44
+ 1. Push all commits/tags to the set remote, typically like `git push origin master`. Override with `--branch`
45
+ 1. Create a 'package' - effectively a compressed tarball - and upload it to the community site
46
+ 1. Have a beer, or glass of wine - you choose.
47
+
48
+ This flow can probably be used for most cookbook maintainers.
49
+
50
+ Usage
51
+ =====
52
+
53
+ Invoke
54
+ ------
55
+
56
+ knife community release COOKBOOK [X.Y.Z | --remote | --branch | --devodd ]
57
+
58
+ Flags
59
+ -----
60
+
61
+ * `X.Y.Z` - String, Version in X.Y.Z format. Manually specify the version.
62
+
63
+ If unspecified, increments to the next x.y.Z version
64
+
65
+ * `--remote REMOTE` - String, Remote repository to push to. Defaults to `origin`
66
+
67
+ * `--branch BRANCHNAME` - String, Branch name. Defaults to `master`
68
+
69
+ * `--devodd` - Boolean. If specified, post-release, will bump the minor version to the next odd number, and generate another commit & push (but no tags).
70
+
71
+ This is a flow that some adopt by having even-only numbered releases, utilizing the [odd numbered ones for development][wiki:oddver].
72
+
73
+
74
+ Some good ideas while working on a cookbook
75
+ -------------------------------------------
76
+
77
+ Creating a `CHANGELOG.md` that details a short message about any changes included in each release is really helpful to anyone looking at your updated cookbook and seeing if it addresses a problem they have, without delving deeper into the code.
78
+
79
+ Updating a `TODO.md` file if there are outstanding known issues, planned work for the next version, etc. A TODO file also helps anyone else in the community try to tackle a problem you haven't figured out or gotten to yet, so they can issue a pull request for your cookbook.
80
+
81
+ Follow [Semantic Versioning][semver] when choosing which version number to increment to. Start your cookbook at 0.1.0, and increment from there, until you are confident enough in a 1.0.0 version.
82
+
83
+ Test, test, test. And then test again.
84
+
85
+
86
+ [brks]: http://berkshelf.com/
87
+ [chef]: http://www.opscode.com/chef/
88
+ [kcsi]: http://wiki.opscode.com/display/chef/Managing+Cookbooks+With+Knife#ManagingCookbooksWithKnife-CookbookSite
89
+ [libr]: https://github.com/applicationsonline/librarian
90
+ [opcs]: http://community.opscode.com/
91
+ [semver]: http://semver.org/
92
+ [wiki:apppkg]: http://en.wikipedia.org/wiki/List_of_software_package_management_systems#Application-level_package_managers
93
+ [wiki:oddver]: http://en.wikipedia.org/wiki/Software_versioning#Odd-numbered_versions_for_development_releases
data/Rakefile ADDED
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ task :default => [:features]
5
+
6
+ # https://github.com/turboladen/tailor
7
+ require 'tailor/rake_task'
8
+ Tailor::RakeTask.new do |task|
9
+ task.file_set('lib/**/*.rb', 'code') do |style|
10
+ style.max_line_length 160, level: :warn
11
+ end
12
+ end
13
+
14
+ require 'cucumber/rake/task'
15
+ Cucumber::Rake::Task.new(:features) do |t|
16
+ t.cucumber_opts = ['features', '-x']
17
+ t.cucumber_opts += ['--format pretty']
18
+ end
19
+
20
+ # https://github.com/guard/guard
21
+ require 'guard'
22
+ desc "Start up guard, does not exit until told to with 'q'."
23
+ task :guard do
24
+ Guard.setup
25
+ Guard::Dsl.evaluate_guardfile(:guardfile => 'Guardfile')
26
+ Guard.start
27
+ end
28
+
29
+ # File lib/tasks/notes.rake
30
+ desc "Find notes in code"
31
+ task :notes do
32
+ puts `grep --exclude=Rakefile -r 'OPTIMIZE:\\|FIXME:\\|TODO:' .`
33
+ end
34
+
35
+ # Clean up any artefacts
36
+ desc "Clean up dev environment cruft like tmp and packages"
37
+ task :clean do
38
+ %w{pkg tmp}.each do |subdir|
39
+ FileUtils.rm_rf(subdir)
40
+ end
41
+ end
@@ -0,0 +1,12 @@
1
+ Feature: Ensure that the Command Line Interface works as designed
2
+ In order to operate the knife community release cookbook tool
3
+ As a Cookbook Maintainer
4
+ I want to ensure the CLI behaves correctly with different arguments
5
+
6
+ Scenario: Running with no arguments produces a failure
7
+ When I run `knife community release`
8
+ Then the exit status should be 1
9
+
10
+ Scenario: Running with too many arguments produces a failure
11
+ When I run `knife community release foo bar baz`
12
+ Then the exit status should be 1
@@ -0,0 +1,14 @@
1
+ # Set up the environment for testing
2
+ require 'aruba/cucumber'
3
+ # require 'aruba-doubles/cucumber'
4
+
5
+ # Before do
6
+ # @dirs = ["tmp/aruba"]
7
+ # end
8
+
9
+ After do |s|
10
+ # Tell Cucumber to quit after this scenario is done - if it failed.
11
+ # This is useful to inspect the 'tmp/aruba' directory before any other
12
+ # steps are executed and clear it out.
13
+ Cucumber.wants_to_quit = true if s.failed?
14
+ end
@@ -0,0 +1,44 @@
1
+ # -*- encoding: utf-8 -*-
2
+ chef_version = ENV.key?('CHEF_VERSION') ? "= #{ENV['CHEF_VERSION']}" : ['~> 10']
3
+ require File.expand_path('../lib/knife-community/version', __FILE__)
4
+
5
+ Gem::Specification.new do |gem|
6
+
7
+ gem.name = "knife-community"
8
+ gem.summary = %q{A Knife plugin to assist with deploying completed Chef cookbooks to the Community Site}
9
+ gem.description = %q{The centralized location for sharing cookbooks is the Community Site, this is a process helper to produce a repeatable method for releasing cookbooks.}
10
+ gem.version = KnifeCommunity::VERSION
11
+
12
+ gem.files = `git ls-files`.split($\)
13
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
+ gem.require_paths = ["lib"]
16
+
17
+ gem.add_dependency 'chef', chef_version
18
+
19
+ # OPTIMIZE: Use Mixlib/Shellout until actions are written in pure ruby
20
+ gem.add_dependency 'mixlib-shellout', '~> 1.1.0'
21
+
22
+ # Using Grit to examin git repo status, and interact with a git repo
23
+ gem.add_dependency 'grit', '~> 2'
24
+
25
+ # A good version comparison library
26
+ gem.add_dependency 'versionomy', '~> 0.4'
27
+
28
+ gem.required_ruby_version = '>= 1.9.2'
29
+
30
+ gem.add_development_dependency 'rake', '~> 0.9'
31
+ gem.add_development_dependency 'rspec', '~> 2.11.0'
32
+ gem.add_development_dependency 'cucumber', '~> 1'
33
+ gem.add_development_dependency 'aruba', '~> 0.4'
34
+ gem.add_development_dependency 'tailor', '~> 1.1'
35
+ gem.add_development_dependency 'travis-lint', '~> 1.4'
36
+ gem.add_development_dependency 'guard', '~> 1.3'
37
+ gem.add_development_dependency 'guard-rspec', '~> 1.2'
38
+ gem.add_development_dependency 'guard-cucumber', '~> 1.2'
39
+
40
+ gem.authors = ["Mike Fiedler"]
41
+ gem.email = ["miketheman@gmail.com"]
42
+ gem.homepage = "http://miketheman.github.com/knife-community"
43
+
44
+ end
@@ -0,0 +1,240 @@
1
+ require 'chef/knife'
2
+
3
+ module KnifeCommunity
4
+ class CommunityRelease < Chef::Knife
5
+
6
+ deps do
7
+ require 'knife-community/version'
8
+ require 'mixlib/shellout'
9
+ require 'chef/config'
10
+ require 'chef/cookbook_loader'
11
+ require 'chef/knife/cookbook_site_share'
12
+ require 'chef/cookbook_site_streaming_uploader'
13
+ require 'grit'
14
+ require 'versionomy'
15
+ require 'json'
16
+ end
17
+
18
+ banner "knife community release COOKBOOK [VERSION] (options)"
19
+
20
+ option :cookbook_path,
21
+ :short => "-o PATH:PATH",
22
+ :long => "--cookbook-path PATH:PATH",
23
+ :description => "A colon-separated path to look for cookbooks in",
24
+ :proc => lambda { |o| o.split(":") }
25
+
26
+ option :remote,
27
+ :short => "-R REMOTE",
28
+ :long => "--remote REMOTE",
29
+ :default => "origin",
30
+ :description => "Remote Git repository to push to"
31
+
32
+ option :branch,
33
+ :short => "-B ",
34
+ :long => "--branch BRANCH",
35
+ :default => "master",
36
+ :description => "Remote Git branch name to push to"
37
+
38
+ option :devodd,
39
+ :long => "--devodd",
40
+ :boolean => true,
41
+ :description => "Odd-numbered development cycle. Bump minor version & commit for development"
42
+
43
+ def run
44
+ self.config = Chef::Config.merge!(config)
45
+ validate_args
46
+ # Set variables for global use
47
+ @cookbook = name_args.first
48
+ @version = Versionomy.parse(name_args.last) if name_args.size > 1
49
+
50
+ ui.msg "Starting to validate the envrionment before changing anything..."
51
+ validate_cookbook_exists
52
+ validate_repo
53
+ validate_repo_clean
54
+ validate_version_sanity
55
+ validate_no_existing_tag
56
+ validate_target_remote_branch
57
+
58
+ ui.msg "All validation steps have passed, making changes..."
59
+ set_new_cb_version
60
+ commit_new_cb_version
61
+ tag_new_cb_version
62
+ git_push_commits
63
+ git_push_tags
64
+
65
+ share_new_version
66
+
67
+ ui.msg "Version #{@version} of the #{@cb_name} has been released!"
68
+ ui.msg "Check it out at http://ckbk.it/#{@cb_name}"
69
+
70
+ # @TODO: Increment the current version to the next available odd number
71
+ # algo = n + 1 + (n % 2)
72
+ if config[:devodd]
73
+ puts "I'm odd!"
74
+ end
75
+
76
+ end #run
77
+
78
+ private
79
+
80
+ # Ensure argumanets are valid, assign values of arguments
81
+ #
82
+ # @param [Array] the global `name_args` object
83
+ def validate_args
84
+ if name_args.size < 1
85
+ ui.error("No cookbook has been specified")
86
+ show_usage
87
+ exit 1
88
+ end
89
+ if name_args.size > 2
90
+ ui.error("Too many arguments are being passed. Please verify.")
91
+ show_usage
92
+ exit 1
93
+ end
94
+ end
95
+
96
+ # Re-used from Chef
97
+ def cookbook_loader
98
+ @cookbook_loader ||= Chef::CookbookLoader.new(config[:cookbook_path])
99
+ end
100
+
101
+ # Validate cookbook existence
102
+ # Since we can have cookbooks in paths that are not named the same as the directory, using
103
+ # a metadata entry to describe the cookbook is better. In its absence, uses the directory name.
104
+ #
105
+ # @return [String] @cb_path, a string with the root directory of the cookbook
106
+ # @return [String] @cb_name, a string with the cookbook's name, either from metadata or interpreted from directory
107
+ def validate_cookbook_exists
108
+ unless cookbook_loader.cookbook_exists?(@cookbook)
109
+ ui.error "Cannot find a cookbook named #{@cookbook} at #{config[:cookbook_path]}"
110
+ exit 2
111
+ end
112
+ cb = cookbook_loader.cookbooks_by_name[@cookbook]
113
+ @cb_path = cb.root_dir
114
+ @cb_name = cb.metadata.name.to_s
115
+ @cb_version = Versionomy.parse(cb.version)
116
+ end
117
+
118
+ # Ensure that the cookbook is in a git repo
119
+ # @TODO: Use Grit instead of shelling out.
120
+ # Couldn't figure out the rev_parse method invocation on a non-repo.
121
+ #
122
+ # @return [String] The absolute file path of the git repository's root
123
+ # @example
124
+ # "/Users/miketheman/git/knife-community"
125
+ def validate_repo
126
+ begin
127
+ @repo_root = shellout("git rev-parse --show-toplevel").stdout.chomp
128
+ rescue Exception => e
129
+ ui.error "There doesn't seem to be a git repo at #{@cb_path}\n#{e}"
130
+ exit 3
131
+ end
132
+ end
133
+
134
+ # Inspect the cookbook directory's git status is good to push.
135
+ # Any existing tracked files should be staged, otherwise error & exit.
136
+ # Untracked files are warned about, but will allow continue.
137
+ # This needs more testing.
138
+ def validate_repo_clean
139
+ @gitrepo = Grit::Repo.new(@repo_root)
140
+ status = @gitrepo.status
141
+ if !status.changed.nil? or status.changed.size != 0 # This has to be a convoluted way to determine a non-empty...
142
+ # Test each for the magic sha_index. Ref: https://github.com/mojombo/grit/issues/142
143
+ status.changed.each do |file|
144
+ case file[1].sha_index
145
+ when "0" * 40
146
+ ui.error "There seem to be unstaged changes in your repo. Either stash or add them."
147
+ exit 4
148
+ else
149
+ ui.msg "There are modified files that have been staged, and will be included in the push."
150
+ end
151
+ end
152
+ elsif status.untracked.size > 0
153
+ ui.warn "There are untracked files in your repo. You might want to look into that."
154
+ end
155
+ end
156
+
157
+ # Ensure that the version specified is larger than the current version
158
+ # If a version wasn't specified on the command line, increment the current by one tiny.
159
+ def validate_version_sanity
160
+ if @version.nil?
161
+ @version = @cb_version.bump(:tiny)
162
+ ui.msg "No version was specified, the new version will be #{@version}"
163
+ end
164
+ if @cb_version >= @version
165
+ ui.error "The current version, #{@cb_version} is either greater or equal to the new version, #{@version}"
166
+ ui.error "For your own sanity, don't release historical cookbooks into the wild."
167
+ exit 5
168
+ end
169
+ end
170
+
171
+ # Ensure that there isn't already a git tag for this version.
172
+ def validate_no_existing_tag
173
+ existing_tags = Array.new
174
+ @gitrepo.tags.each { |tag| existing_tags << tag.name }
175
+ if existing_tags.include?(@version.to_s)
176
+ ui.error "This version tag has already been committed to the repo."
177
+ ui.error "Are you sure you haven't released this already?"
178
+ exit 6
179
+ end
180
+ end
181
+
182
+ # Ensure that the remote and branch are indeed valid. We provide defaults in options.
183
+ def validate_target_remote_branch
184
+ remote_path = File.join(config[:remote], config[:branch])
185
+
186
+ remotes = Array.new
187
+ @gitrepo.remotes.each { |remote| remotes << remote.name }
188
+ unless remotes.include?(remote_path)
189
+ ui.error "The remote/branch specified does not seem to exist."
190
+ exit 7
191
+ end
192
+ end
193
+
194
+ # Replace the existing version string with the new version
195
+ def set_new_cb_version
196
+ metadata_file = File.join(@cb_path, "metadata.rb")
197
+ fi = File.read(metadata_file)
198
+ fi.gsub!(@cb_version.to_s, @version.to_s)
199
+ fo = File.open(metadata_file, 'w') { |file| file.puts fi }
200
+ end
201
+
202
+ # Using shellout as needed.
203
+ # @todo Struggled with the Grit::Repo#add for hours.
204
+ def commit_new_cb_version
205
+ shellout("git add metadata.rb")
206
+ @gitrepo.commit_index("release v#{@version}")
207
+ end
208
+
209
+ def tag_new_cb_version
210
+ shellout("git tag -a -m 'release v#{@version}' #{@version}")
211
+ end
212
+
213
+ # Apparently Grit does not have any `push` semantics yet.
214
+ def git_push_commits
215
+ shellout("git push #{config[:remote]} #{config[:branch]}")
216
+ end
217
+
218
+ def git_push_tags
219
+ shellout("git push #{config[:remote]} --tags")
220
+ end
221
+
222
+ def share_new_version
223
+ # Need to find the existing cookbook's category. Thankfully, this is readily available via REST/JSON.
224
+ response = Net::HTTP.get_response("cookbooks.opscode.com", "/api/v1/cookbooks/#{@cb_name}")
225
+ category = JSON.parse(response.body)['category'] ||= "Other"
226
+
227
+ cb_share = Chef::Knife::CookbookSiteShare.new
228
+ cb_share.name_args = [@cb_name, category]
229
+ cb_share.run
230
+ end
231
+
232
+ def shellout(command)
233
+ proc = Mixlib::ShellOut.new(command, :cwd => @cb_path)
234
+ proc.run_command
235
+ proc.error!
236
+ return proc
237
+ end
238
+
239
+ end #class
240
+ end #module
@@ -0,0 +1,3 @@
1
+ module KnifeCommunity
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,2 @@
1
+ require 'rspec'
2
+ require 'chef/knife/community_release'
metadata ADDED
@@ -0,0 +1,274 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: knife-community
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Mike Fiedler
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-17 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: chef
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '10'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '10'
30
+ - !ruby/object:Gem::Dependency
31
+ name: mixlib-shellout
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 1.1.0
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 1.1.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: grit
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '2'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '2'
62
+ - !ruby/object:Gem::Dependency
63
+ name: versionomy
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '0.4'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '0.4'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rake
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: '0.9'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: '0.9'
94
+ - !ruby/object:Gem::Dependency
95
+ name: rspec
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: 2.11.0
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: 2.11.0
110
+ - !ruby/object:Gem::Dependency
111
+ name: cucumber
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: '1'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ~>
124
+ - !ruby/object:Gem::Version
125
+ version: '1'
126
+ - !ruby/object:Gem::Dependency
127
+ name: aruba
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ~>
132
+ - !ruby/object:Gem::Version
133
+ version: '0.4'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ~>
140
+ - !ruby/object:Gem::Version
141
+ version: '0.4'
142
+ - !ruby/object:Gem::Dependency
143
+ name: tailor
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ~>
148
+ - !ruby/object:Gem::Version
149
+ version: '1.1'
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ~>
156
+ - !ruby/object:Gem::Version
157
+ version: '1.1'
158
+ - !ruby/object:Gem::Dependency
159
+ name: travis-lint
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ~>
164
+ - !ruby/object:Gem::Version
165
+ version: '1.4'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ~>
172
+ - !ruby/object:Gem::Version
173
+ version: '1.4'
174
+ - !ruby/object:Gem::Dependency
175
+ name: guard
176
+ requirement: !ruby/object:Gem::Requirement
177
+ none: false
178
+ requirements:
179
+ - - ~>
180
+ - !ruby/object:Gem::Version
181
+ version: '1.3'
182
+ type: :development
183
+ prerelease: false
184
+ version_requirements: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ~>
188
+ - !ruby/object:Gem::Version
189
+ version: '1.3'
190
+ - !ruby/object:Gem::Dependency
191
+ name: guard-rspec
192
+ requirement: !ruby/object:Gem::Requirement
193
+ none: false
194
+ requirements:
195
+ - - ~>
196
+ - !ruby/object:Gem::Version
197
+ version: '1.2'
198
+ type: :development
199
+ prerelease: false
200
+ version_requirements: !ruby/object:Gem::Requirement
201
+ none: false
202
+ requirements:
203
+ - - ~>
204
+ - !ruby/object:Gem::Version
205
+ version: '1.2'
206
+ - !ruby/object:Gem::Dependency
207
+ name: guard-cucumber
208
+ requirement: !ruby/object:Gem::Requirement
209
+ none: false
210
+ requirements:
211
+ - - ~>
212
+ - !ruby/object:Gem::Version
213
+ version: '1.2'
214
+ type: :development
215
+ prerelease: false
216
+ version_requirements: !ruby/object:Gem::Requirement
217
+ none: false
218
+ requirements:
219
+ - - ~>
220
+ - !ruby/object:Gem::Version
221
+ version: '1.2'
222
+ description: The centralized location for sharing cookbooks is the Community Site,
223
+ this is a process helper to produce a repeatable method for releasing cookbooks.
224
+ email:
225
+ - miketheman@gmail.com
226
+ executables: []
227
+ extensions: []
228
+ extra_rdoc_files: []
229
+ files:
230
+ - .gitignore
231
+ - .travis.yml
232
+ - Gemfile
233
+ - Guardfile
234
+ - LICENSE
235
+ - README.md
236
+ - Rakefile
237
+ - features/cli.feature
238
+ - features/support/env.rb
239
+ - knife-community.gemspec
240
+ - lib/chef/knife/community_release.rb
241
+ - lib/knife-community/version.rb
242
+ - spec/spec_helper.rb
243
+ homepage: http://miketheman.github.com/knife-community
244
+ licenses: []
245
+ post_install_message:
246
+ rdoc_options: []
247
+ require_paths:
248
+ - lib
249
+ required_ruby_version: !ruby/object:Gem::Requirement
250
+ none: false
251
+ requirements:
252
+ - - ! '>='
253
+ - !ruby/object:Gem::Version
254
+ version: 1.9.2
255
+ required_rubygems_version: !ruby/object:Gem::Requirement
256
+ none: false
257
+ requirements:
258
+ - - ! '>='
259
+ - !ruby/object:Gem::Version
260
+ version: '0'
261
+ segments:
262
+ - 0
263
+ hash: -1152703589745345809
264
+ requirements: []
265
+ rubyforge_project:
266
+ rubygems_version: 1.8.24
267
+ signing_key:
268
+ specification_version: 3
269
+ summary: A Knife plugin to assist with deploying completed Chef cookbooks to the Community
270
+ Site
271
+ test_files:
272
+ - features/cli.feature
273
+ - features/support/env.rb
274
+ - spec/spec_helper.rb