knife-spork 0.1.11 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/.rvmrc +1 -0
- data/CHANGELOG.md +37 -23
- data/Gemfile +3 -0
- data/LICENSE +35 -0
- data/README.md +202 -219
- data/Rakefile +2 -122
- data/knife-spork.gemspec +20 -67
- data/lib/chef/knife/spork-bump.rb +31 -205
- data/lib/chef/knife/spork-check.rb +77 -125
- data/lib/chef/knife/spork-info.rb +30 -0
- data/lib/chef/knife/spork-promote.rb +105 -417
- data/lib/chef/knife/spork-upload.rb +71 -298
- data/lib/knife-spork.rb +1 -1
- data/lib/knife-spork/plugins.rb +22 -0
- data/lib/knife-spork/plugins/campfire.rb +47 -0
- data/lib/knife-spork/plugins/eventinator.rb +71 -0
- data/lib/knife-spork/plugins/foodcritic.rb +41 -0
- data/lib/knife-spork/plugins/git.rb +123 -0
- data/lib/knife-spork/plugins/graphite.rb +25 -0
- data/lib/knife-spork/plugins/hip_chat.rb +50 -0
- data/lib/knife-spork/plugins/irccat.rb +48 -0
- data/lib/knife-spork/plugins/plugin.rb +74 -0
- data/lib/knife-spork/runner.rb +166 -0
- data/plugins/Campfire.md +43 -0
- data/plugins/Eventinator.md +30 -0
- data/plugins/Foodcritic.md +53 -0
- data/plugins/Git.md +46 -0
- data/plugins/Graphite.md +30 -0
- data/plugins/HipChat.md +50 -0
- data/plugins/Irccat.md +44 -0
- data/plugins/README.md +70 -0
- data/plugins/Template.md +34 -0
- metadata +37 -27
data/Rakefile
CHANGED
@@ -1,122 +1,2 @@
|
|
1
|
-
|
2
|
-
require '
|
3
|
-
require 'date'
|
4
|
-
|
5
|
-
#############################################################################
|
6
|
-
#
|
7
|
-
# Helper functions
|
8
|
-
#
|
9
|
-
#############################################################################
|
10
|
-
|
11
|
-
def name
|
12
|
-
@name ||= Dir['*.gemspec'].first.split('.').first
|
13
|
-
end
|
14
|
-
|
15
|
-
def version
|
16
|
-
line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/]
|
17
|
-
line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
|
18
|
-
end
|
19
|
-
|
20
|
-
def date
|
21
|
-
Date.today.to_s
|
22
|
-
end
|
23
|
-
|
24
|
-
def rubyforge_project
|
25
|
-
name
|
26
|
-
end
|
27
|
-
|
28
|
-
def gemspec_file
|
29
|
-
"#{name}.gemspec"
|
30
|
-
end
|
31
|
-
|
32
|
-
def gem_file
|
33
|
-
"#{name}-#{version}.gem"
|
34
|
-
end
|
35
|
-
|
36
|
-
def replace_header(head, header_name)
|
37
|
-
head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
|
38
|
-
end
|
39
|
-
|
40
|
-
#############################################################################
|
41
|
-
#
|
42
|
-
# Standard tasks
|
43
|
-
#
|
44
|
-
#############################################################################
|
45
|
-
|
46
|
-
task :default => :validate
|
47
|
-
|
48
|
-
desc "Open an irb session preloaded with this library"
|
49
|
-
task :console do
|
50
|
-
sh "irb -rubygems -r ./lib/#{name}.rb"
|
51
|
-
end
|
52
|
-
|
53
|
-
#############################################################################
|
54
|
-
#
|
55
|
-
# Custom tasks (add your own tasks here)
|
56
|
-
#
|
57
|
-
#############################################################################
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
#############################################################################
|
62
|
-
#
|
63
|
-
# Packaging tasks
|
64
|
-
#
|
65
|
-
#############################################################################
|
66
|
-
|
67
|
-
desc "Create tag v#{version} and build and push #{gem_file} to Rubygems"
|
68
|
-
task :release => :build do
|
69
|
-
unless `git branch` =~ /^\* master$/
|
70
|
-
puts "You must be on the master branch to release!"
|
71
|
-
exit!
|
72
|
-
end
|
73
|
-
sh "git commit --allow-empty -a -m 'Release #{version}'"
|
74
|
-
sh "git tag v#{version}"
|
75
|
-
sh "git push origin master"
|
76
|
-
sh "git push origin v#{version}"
|
77
|
-
sh "gem push pkg/#{name}-#{version}.gem"
|
78
|
-
end
|
79
|
-
|
80
|
-
desc "Build #{gem_file} into the pkg directory"
|
81
|
-
task :build => :gemspec do
|
82
|
-
sh "mkdir -p pkg"
|
83
|
-
sh "gem build #{gemspec_file}"
|
84
|
-
sh "mv #{gem_file} pkg"
|
85
|
-
end
|
86
|
-
|
87
|
-
desc "Generate #{gemspec_file}"
|
88
|
-
task :gemspec => :validate do
|
89
|
-
# read spec file and split out manifest section
|
90
|
-
spec = File.read(gemspec_file)
|
91
|
-
head, manifest, tail = spec.split(" # = MANIFEST =\n")
|
92
|
-
|
93
|
-
# replace name version and date
|
94
|
-
replace_header(head, :name)
|
95
|
-
replace_header(head, :version)
|
96
|
-
replace_header(head, :date)
|
97
|
-
#comment this out if your rubyforge_project has a different name
|
98
|
-
replace_header(head, :rubyforge_project)
|
99
|
-
|
100
|
-
# determine file list from git ls-files
|
101
|
-
files = `git ls-files`.
|
102
|
-
split("\n").
|
103
|
-
sort.
|
104
|
-
reject { |file| file =~ /^\./ }.
|
105
|
-
reject { |file| file =~ /^(rdoc|pkg)/ }.
|
106
|
-
map { |file| " #{file}" }.
|
107
|
-
join("\n")
|
108
|
-
|
109
|
-
# piece file back together and write
|
110
|
-
manifest = " s.files = %w[\n#{files}\n ]\n"
|
111
|
-
spec = [head, manifest, tail].join(" # = MANIFEST =\n")
|
112
|
-
File.open(gemspec_file, 'w') { |io| io.write(spec) }
|
113
|
-
puts "Updated #{gemspec_file}"
|
114
|
-
end
|
115
|
-
|
116
|
-
desc "Validate #{gemspec_file}"
|
117
|
-
task :validate do
|
118
|
-
unless Dir['VERSION*'].empty?
|
119
|
-
puts "A `VERSION` file at root level violates Gem best practices."
|
120
|
-
exit!
|
121
|
-
end
|
122
|
-
end
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require 'bundler/gem_tasks'
|
data/knife-spork.gemspec
CHANGED
@@ -1,68 +1,21 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
## as you like.
|
22
|
-
s.summary = "A workflow plugin to help many devs work with the same chef repo/server"
|
23
|
-
s.description = "A workflow plugin to help many devs work with the same chef repo/server"
|
24
|
-
|
25
|
-
## List the primary authors. If there are a bunch of authors, it's probably
|
26
|
-
## better to set the email to an email list or something. If you don't have
|
27
|
-
## a custom homepage, consider using your GitHub URL or the like.
|
28
|
-
s.authors = ["Jon Cowie"]
|
29
|
-
s.email = 'jonlives@gmail.com'
|
30
|
-
s.homepage = 'https://github.com/jonlives/knife-spork'
|
31
|
-
|
32
|
-
## This gets added to the $LOAD_PATH so that 'lib/NAME.rb' can be required as
|
33
|
-
## require 'NAME.rb' or'/lib/NAME/file.rb' can be as require 'NAME/file.rb'
|
34
|
-
s.require_paths = %w[lib]
|
35
|
-
|
36
|
-
## Specify any RDoc options here. You'll want to add your README and
|
37
|
-
## LICENSE files to the extra_rdoc_files list.
|
38
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
39
|
-
s.extra_rdoc_files = %w[README.md]
|
40
|
-
|
41
|
-
## List your runtime dependencies here. Runtime dependencies are those
|
42
|
-
## that are needed for an end user to actually USE your code.
|
43
|
-
s.add_dependency('chef', [">= 0.10.4"])
|
44
|
-
s.add_dependency('git', [">= 1.2.5"])
|
45
|
-
s.add_dependency('app_conf', [">= 0.4.0"])
|
46
|
-
s.add_dependency('hipchat', [">= 0.4.0"])
|
47
|
-
|
48
|
-
## Leave this section as-is. It will be automatically generated from the
|
49
|
-
## contents of your Git repository via the gemspec task. DO NOT REMOVE
|
50
|
-
## THE MANIFEST COMMENTS, they are used as delimiters by the task.
|
51
|
-
# = MANIFEST =
|
52
|
-
s.files = %w[
|
53
|
-
README.md
|
54
|
-
CHANGELOG.md
|
55
|
-
Rakefile
|
56
|
-
knife-spork.gemspec
|
57
|
-
lib/chef/knife/spork-bump.rb
|
58
|
-
lib/chef/knife/spork-check.rb
|
59
|
-
lib/chef/knife/spork-promote.rb
|
60
|
-
lib/chef/knife/spork-upload.rb
|
61
|
-
lib/knife-spork.rb
|
62
|
-
]
|
63
|
-
# = MANIFEST =
|
64
|
-
|
65
|
-
## Test files will be grabbed from the file list. Make sure the path glob
|
66
|
-
## matches what you actually use.
|
67
|
-
s.test_files = s.files.select { |path| path =~ /^test\/test_.*\.rb/ }
|
1
|
+
$:.push File.expand_path('../lib', __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |gem|
|
4
|
+
gem.name = 'knife-spork'
|
5
|
+
gem.version = '1.0.0'
|
6
|
+
gem.authors = ["Jon Cowie"]
|
7
|
+
gem.email = 'jonlives@gmail.com'
|
8
|
+
gem.homepage = 'https://github.com/jonlives/knife-spork'
|
9
|
+
gem.summary = "A workflow plugin to help many devs work with the same chef repo/server"
|
10
|
+
gem.description = "A workflow plugin to help many devs work with the same chef repo/server"
|
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.name = "knife-spork"
|
16
|
+
gem.require_paths = ["lib"]
|
17
|
+
|
18
|
+
gem.add_runtime_dependency 'chef', '>= 0.10.4'
|
19
|
+
gem.add_runtime_dependency 'git', '>= 1.2.5'
|
20
|
+
gem.add_runtime_dependency 'app_conf', '>= 0.4.0'
|
68
21
|
end
|
@@ -1,228 +1,54 @@
|
|
1
|
-
#
|
2
|
-
# Modifying Author:: Jon Cowie (<jonlives@gmail.com>)
|
3
|
-
# Copyright:: Copyright (c) 2011 Jon Cowie
|
4
|
-
# License:: GPL
|
5
|
-
|
6
|
-
# Based on the knife-cookbook-bump plugin by:
|
7
|
-
# Alalanta (no license specified)
|
8
|
-
|
9
|
-
require 'app_conf'
|
10
1
|
require 'chef/knife'
|
11
|
-
require '
|
12
|
-
require 'chef/cookbook_uploader'
|
2
|
+
require 'knife-spork/runner'
|
13
3
|
|
14
4
|
module KnifeSpork
|
15
5
|
class SporkBump < Chef::Knife
|
6
|
+
include KnifeSpork::Runner
|
16
7
|
|
17
|
-
TYPE_INDEX = {
|
8
|
+
TYPE_INDEX = { :major => 0, :minor => 1, :patch => 2, :manual => 3 }.freeze
|
18
9
|
|
19
|
-
banner
|
20
|
-
|
21
|
-
@@gitavail = true
|
22
|
-
deps do
|
23
|
-
begin
|
24
|
-
require "git"
|
25
|
-
rescue LoadError
|
26
|
-
@@gitavail = false
|
27
|
-
end
|
28
|
-
end
|
10
|
+
banner 'knife spork bump COOKBOOK [major|minor|patch|manual]'
|
29
11
|
|
30
12
|
def run
|
31
|
-
|
32
|
-
if RUBY_VERSION.to_f < 1.9
|
33
|
-
ui.fatal "Sorry, knife-spork requires ruby 1.9 or newer."
|
34
|
-
exit 1
|
35
|
-
end
|
36
|
-
|
37
13
|
self.config = Chef::Config.merge!(config)
|
14
|
+
@cookbook = load_cookbook(name_args.first)
|
38
15
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
@conf.load("#{config[:cookbook_path].first.gsub("cookbooks","")}config/spork-config.yml")
|
43
|
-
ui.msg "Loaded config file #{config[:cookbook_path].first.gsub("cookbooks","")}config/spork-config.yml...\n\n"
|
44
|
-
end
|
45
|
-
|
46
|
-
if File.exists?("/etc/spork-config.yml")
|
47
|
-
@conf.load("/etc/spork-config.yml")
|
48
|
-
ui.msg "Loaded config file /etc/spork-config.yml...\n\n"
|
49
|
-
end
|
50
|
-
|
51
|
-
if File.exists?(File.expand_path("~/.chef/spork-config.yml"))
|
52
|
-
@conf.load(File.expand_path("~/.chef/spork-config.yml"))
|
53
|
-
ui.msg "Loaded config file #{File.expand_path("~/.chef/spork-config.yml")}...\n\n"
|
54
|
-
end
|
55
|
-
|
56
|
-
bump_type=""
|
57
|
-
|
58
|
-
if !config.has_key?(:cookbook_path)
|
59
|
-
ui.fatal "No default cookbook_path; Specify with -o or fix your knife.rb."
|
60
|
-
show_usage
|
61
|
-
exit 1
|
62
|
-
end
|
63
|
-
|
64
|
-
if name_args.size == 0
|
65
|
-
show_usage
|
66
|
-
exit 0
|
67
|
-
end
|
68
|
-
|
69
|
-
if name_args.size == 3
|
70
|
-
bump_type = name_args[1]
|
71
|
-
elsif name_args.size == 2
|
72
|
-
bump_type = name_args.last
|
73
|
-
elsif name_args.size == 1
|
74
|
-
bump_type = "patch"
|
75
|
-
else
|
76
|
-
ui.fatal "Please specify the cookbook whose version you which to bump, and the type of bump you wish to apply."
|
77
|
-
show_usage
|
78
|
-
exit 1
|
79
|
-
end
|
80
|
-
|
81
|
-
unless TYPE_INDEX.has_key?(bump_type)
|
82
|
-
ui.fatal "Sorry, '#{name_args.last}' isn't a valid bump type. Specify one of 'major', 'minor', 'patch' or 'manual'"
|
83
|
-
show_usage
|
84
|
-
exit 1
|
85
|
-
end
|
86
|
-
|
87
|
-
cookbook = name_args.first
|
88
|
-
cookbook_path = cookbook_repo[cookbook].root_dir.gsub("#{cookbook}","")
|
89
|
-
|
90
|
-
if !@conf.git.nil? && @conf.git.enabled
|
91
|
-
if !@@gitavail
|
92
|
-
ui.msg "Git gem not available, skipping git pull.\n\n"
|
93
|
-
else
|
94
|
-
git_pull_if_repo([cookbook_path])
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
if bump_type == "manual"
|
99
|
-
manual_version = name_args.last
|
100
|
-
patch_manual(cookbook_path, cookbook, manual_version)
|
101
|
-
else
|
102
|
-
patch(cookbook_path, cookbook, bump_type)
|
103
|
-
end
|
104
|
-
|
105
|
-
if !@conf.git.nil? && @conf.git.enabled
|
106
|
-
if !@@gitavail
|
107
|
-
ui.msg "Git gem not available, skipping git add.\n\n"
|
108
|
-
else
|
109
|
-
git_add(cookbook)
|
110
|
-
end
|
111
|
-
end
|
16
|
+
run_plugins(:before_bump)
|
17
|
+
bump
|
18
|
+
run_plugins(:after_bump)
|
112
19
|
end
|
113
20
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
Chef::CookbookLoader.new(config[:cookbook_path])
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
def patch(cookbook_path, cookbook, type)
|
122
|
-
t = TYPE_INDEX[type]
|
123
|
-
current_version = get_version(cookbook_path, cookbook).split(".").map{|i| i.to_i}
|
124
|
-
bumped_version = current_version.clone
|
125
|
-
bumped_version[t] = bumped_version[t] + 1
|
126
|
-
while t < 2
|
127
|
-
t+=1
|
128
|
-
bumped_version[t] = 0
|
129
|
-
end
|
130
|
-
metadata_file = File.join(cookbook_path, cookbook, "metadata.rb")
|
131
|
-
old_version = current_version.join('.')
|
132
|
-
new_version = bumped_version.join('.')
|
133
|
-
update_version(new_version, metadata_file)
|
134
|
-
ui.msg("Bumping #{type} level of the #{cookbook} cookbook from #{old_version} to #{new_version}\n\n")
|
135
|
-
end
|
136
|
-
|
137
|
-
def patch_manual(cookbook_path, cookbook, version)
|
138
|
-
current_version = get_version(cookbook_path, cookbook)
|
139
|
-
v = version.split(".")
|
140
|
-
if v.size < 3 or v.size > 3
|
141
|
-
ui.msg "That isn't a valid version number to bump to."
|
142
|
-
exit 1
|
143
|
-
end
|
21
|
+
private
|
22
|
+
def bump
|
23
|
+
old_version = @cookbook.version
|
144
24
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
25
|
+
if bump_type == 3
|
26
|
+
# manual bump
|
27
|
+
version_array = manual_bump_version.split('.')
|
28
|
+
else
|
29
|
+
# major, minor, or patch bump
|
30
|
+
version_array = old_version.split('.').collect{ |i| i.to_i }
|
31
|
+
version_array[bump_type] += 1
|
32
|
+
((bump_type+1)..2).each{ |i| version_array[i] = 0 } # reset all lower version numbers to 0
|
150
33
|
end
|
151
34
|
|
152
|
-
|
153
|
-
update_version(version, metadata_file)
|
154
|
-
ui.msg("Manually bumped version of the #{cookbook} cookbook from #{current_version} to #{version}")
|
155
|
-
end
|
35
|
+
new_version = version_array.join('.')
|
156
36
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
open_file.close
|
161
|
-
body_of_file.gsub!(/version\s+"[0-9\.]+"/, "version \"#{new_version}\"")
|
162
|
-
File.open(metadata_file, "w") { |file| file << body_of_file }
|
163
|
-
end
|
37
|
+
metadata_file = "#{@cookbook.root_dir}/metadata.rb"
|
38
|
+
new_contents = File.read(metadata_file).gsub(/version\s+['"][0-9\.]+['"]/, "version \"#{new_version}\"")
|
39
|
+
File.open(metadata_file, 'w'){ |f| f.write(new_contents) }
|
164
40
|
|
165
|
-
|
166
|
-
loader = ::Chef::CookbookLoader.new(cookbook_path)
|
167
|
-
return loader[cookbook].version
|
41
|
+
ui.info "Successfully bumped #{@cookbook.name} to v#{new_version}!"
|
168
42
|
end
|
169
43
|
|
170
|
-
def
|
171
|
-
|
172
|
-
l = Logger.new strio
|
173
|
-
cookbook_path = cookbook_repo[cookbook].root_dir.gsub("#{cookbook}","")
|
174
|
-
begin
|
175
|
-
path = cookbook_path.gsub("/site-cookbooks","").gsub("/cookbooks","")
|
176
|
-
ui.msg "Opening git repo #{path}\n\n"
|
177
|
-
g = Git.open(path, :log => Logger.new(strio))
|
178
|
-
ui.msg "Git add'ing #{cookbook_path}#{cookbook}/metadata.rb\n\n"
|
179
|
-
g.add("#{cookbook_path}/#{cookbook}/metadata.rb")
|
180
|
-
rescue ArgumentError => e
|
181
|
-
ui.warn "Git: The root of your chef repo doesn't look like it's a git repo. Skipping git add...\n\n"
|
182
|
-
rescue
|
183
|
-
ui.warn "Git: Cookbook bump succeeded, but something went wrong with git add metadata.rb, so you'll want to manually git add it. Dumping log info..."
|
184
|
-
ui.warn "#{strio.string}"
|
185
|
-
end
|
44
|
+
def bump_type
|
45
|
+
TYPE_INDEX[(name_args[1] || 'patch').to_sym]
|
186
46
|
end
|
187
|
-
|
188
|
-
def git_pull_if_repo(cookbook_path)
|
189
|
-
strio = StringIO.new
|
190
|
-
l = Logger.new strio
|
191
|
-
begin
|
192
|
-
path = cookbook_path[0].gsub("/site-cookbooks","").gsub("/cookbooks","")
|
193
|
-
ui.msg "Opening git repo #{path}\n\n"
|
194
|
-
g = Git.open(path, :log => Logger.new(strio))
|
195
|
-
ui.msg "Pulling latest changes from git\n\n"
|
196
|
-
output = IO.popen ("cd #{path} && git pull 2>&1")
|
197
|
-
Process.wait
|
198
|
-
exit_code = $?
|
199
|
-
if exit_code.exitstatus == 0
|
200
|
-
ui.msg "#{output.read()}\n"
|
201
|
-
else
|
202
|
-
ui.error "#{output.read()}\n"
|
203
|
-
exit 1
|
204
|
-
end
|
205
|
-
|
206
|
-
ui.msg "Pulling latest changes from git submodules (if any)\n\n"
|
207
|
-
output = IO.popen ("cd #{path} && git submodule foreach git pull 2>&1")
|
208
|
-
Process.wait
|
209
|
-
exit_code = $?
|
210
|
-
if exit_code.exitstatus == 0
|
211
|
-
ui.msg "#{output.read()}\n"
|
212
|
-
else
|
213
|
-
ui.error "#{output.read()}\n"
|
214
|
-
exit 1
|
215
|
-
end
|
216
|
-
rescue ArgumentError => e
|
217
|
-
ui.warn "Git: #{cookbook_path.join} doesn't look like it's a git repo. Skipping git pull...\n\n"
|
218
|
-
end
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
end
|
223
47
|
|
224
|
-
|
225
|
-
|
226
|
-
|
48
|
+
def manual_bump_version
|
49
|
+
version = name_args.last
|
50
|
+
validate_version!(version)
|
51
|
+
version
|
227
52
|
end
|
53
|
+
end
|
228
54
|
end
|