chef-steel 0.0.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.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.rspec +2 -0
- data/LICENSE.txt +21 -0
- data/README.md +6 -0
- data/Rakefile +6 -0
- data/bin/steel +7 -0
- data/chef-steel.gemspec +39 -0
- data/lib/chef/steel.rb +6 -0
- data/lib/chef/steel/exceptions.rb +11 -0
- data/lib/chef/steel/filetools.rb +33 -0
- data/lib/chef/steel/git.rb +30 -0
- data/lib/chef/steel/logger.rb +38 -0
- data/lib/chef/steel/runner.rb +216 -0
- data/lib/chef/steel/version.rb +5 -0
- data/steel.yml.example +21 -0
- metadata +137 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0347e49b84d3e3d0e0075ce03507cbff50721da7
|
4
|
+
data.tar.gz: 289cfe57544a0f38d6ea7135f04a651a9055d39d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 27be27899ebd28569bd4fe2527066d7e09eae74e48c4cf65e215415ccadeb53f735e1b1cea681236a7a9b53363f00c37983b1cced34362547c558e008556755c
|
7
|
+
data.tar.gz: 9806a3bcc0a3a19b157179892792171df82f8f49ba81da29fbc0aa469831da06a2e94892aa9ae5a7ae444134bd5d7ac5a87a551324cc8ea8371bc31854c372a2
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.gem
|
data/.rspec
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Ryan Frantz
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
data/Rakefile
ADDED
data/bin/steel
ADDED
data/chef-steel.gemspec
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "chef/steel/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "chef-steel"
|
8
|
+
spec.version = Chef::Steel::VERSION
|
9
|
+
spec.authors = ["Ryan Frantz"]
|
10
|
+
spec.email = ["ryanleefrantz@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{A tool to keep testing-related configurations up-to-date}
|
13
|
+
spec.description = <<-EOD
|
14
|
+
Hone your tools with chef-steel!
|
15
|
+
|
16
|
+
chef-steel is a tool that can keep testing-related configurations up-to-date
|
17
|
+
within one or more repos.
|
18
|
+
|
19
|
+
If you work within many different repos that share a common set of testing tools
|
20
|
+
(i.e. Rubocop, Foodcritic, Travis, Jenkins, etc.) it can be easy for their
|
21
|
+
configuration to drift. With chef-steel you can update one or more of these
|
22
|
+
configuration files from a central repository, as needed.
|
23
|
+
EOD
|
24
|
+
spec.homepage = 'https://github.com/RyanFrantz/chef-steel'
|
25
|
+
spec.license = 'MIT'
|
26
|
+
|
27
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
28
|
+
f.match(%r{^(test|spec|features)/})
|
29
|
+
end
|
30
|
+
spec.bindir = "bin"
|
31
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
32
|
+
spec.require_paths = ["lib"]
|
33
|
+
|
34
|
+
spec.add_runtime_dependency 'choice', '~> 0.2', '>= 0.2.0'
|
35
|
+
spec.add_runtime_dependency 'colorize', '~> 0.8', '>= 0.8.1'
|
36
|
+
|
37
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
38
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
39
|
+
end
|
data/lib/chef/steel.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'chef/steel/logger'
|
2
|
+
require 'digest'
|
3
|
+
|
4
|
+
module Chef
|
5
|
+
module Steel
|
6
|
+
module FileTools
|
7
|
+
|
8
|
+
include Chef::Steel::Logger
|
9
|
+
|
10
|
+
# Compare two files' digests to determine if they're the same file.
|
11
|
+
# Returns true/false based on the comparison of digest strings.
|
12
|
+
def same_file?(local_file, remote_file)
|
13
|
+
local_digest = Digest::SHA256.file(local_file).hexdigest
|
14
|
+
remote_digest = Digest::SHA256.file(remote_file).hexdigest
|
15
|
+
local_digest == remote_digest
|
16
|
+
end
|
17
|
+
|
18
|
+
# Copy a file from its source to its destination.
|
19
|
+
def copy_file(src, dst)
|
20
|
+
FileUtils.cp(src, dst)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Remove the temporary directory using a naive guard to ensure we're
|
24
|
+
# deleting what we expect.
|
25
|
+
def clean_up(tmp_dir)
|
26
|
+
info "\nCleaning up temporary directory '#{tmp_dir}"
|
27
|
+
re_tmp_dir = Regexp.new('chef-steel')
|
28
|
+
FileUtils.rm_rf(tmp_dir) if tmp_dir.match(re_tmp_dir)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'chef/steel/logger'
|
2
|
+
|
3
|
+
module Chef
|
4
|
+
module Steel
|
5
|
+
module Git
|
6
|
+
|
7
|
+
include Chef::Steel::Logger
|
8
|
+
|
9
|
+
# Clone a repo into a given destination. We assume the destination is
|
10
|
+
# a temporary directory.
|
11
|
+
def git_clone(repo, destination)
|
12
|
+
result = `git clone -q #{repo} #{destination}`
|
13
|
+
if $?.exitstatus != 0
|
14
|
+
error "Failed to clone #{repo} into #{destination} (Exit status: #{$?.exitstatus})!"
|
15
|
+
error "Result: #{result}" unless result.empty?
|
16
|
+
exit $?.exitstatus
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def git_diff(local_file, remote_file)
|
21
|
+
result = `git diff --color=always #{local_file} #{remote_file}`
|
22
|
+
log ""
|
23
|
+
result.split("\n").each do |line|
|
24
|
+
raw_log "\t" + line
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Chef
|
2
|
+
module Steel
|
3
|
+
module Logger
|
4
|
+
|
5
|
+
require 'colorize'
|
6
|
+
|
7
|
+
# Print the raw string (including escape sequences, if any).
|
8
|
+
def raw_log(msg = '')
|
9
|
+
puts msg
|
10
|
+
end
|
11
|
+
|
12
|
+
def prompt(msg = '')
|
13
|
+
print msg
|
14
|
+
end
|
15
|
+
|
16
|
+
def info(msg = '')
|
17
|
+
log(msg, :green)
|
18
|
+
end
|
19
|
+
|
20
|
+
def notice(msg = '')
|
21
|
+
log(msg, :light_magenta)
|
22
|
+
end
|
23
|
+
|
24
|
+
def warn(msg = '')
|
25
|
+
log(msg, :yellow)
|
26
|
+
end
|
27
|
+
|
28
|
+
def error(msg = '')
|
29
|
+
log(msg, :red)
|
30
|
+
end
|
31
|
+
|
32
|
+
def log(msg = '', color = nil)
|
33
|
+
puts msg.colorize(color)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,216 @@
|
|
1
|
+
require 'chef/steel/git'
|
2
|
+
require 'chef/steel/exceptions'
|
3
|
+
require 'chef/steel/filetools'
|
4
|
+
require 'chef/steel/logger'
|
5
|
+
require 'chef/steel/version'
|
6
|
+
require 'choice'
|
7
|
+
require 'tmpdir' # Extends Dir
|
8
|
+
require 'yaml'
|
9
|
+
|
10
|
+
module Chef
|
11
|
+
module Steel
|
12
|
+
class Runner
|
13
|
+
|
14
|
+
include Chef::Steel::FileTools
|
15
|
+
include Chef::Steel::Git
|
16
|
+
include Chef::Steel::Logger
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@config = config
|
20
|
+
@clone_destination = nil # Wait until we need it...
|
21
|
+
@file_candidates = nil # Wait until we need it...
|
22
|
+
end
|
23
|
+
|
24
|
+
# Validate we're in a git repo. If not, we likely don't want to do anything.
|
25
|
+
def validate_in_repo
|
26
|
+
unless File.exist?('.git')
|
27
|
+
raise NotInAGitRepository, "We don't appear to be inside a Git repository!"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# A hash of values describing our config.
|
32
|
+
def config
|
33
|
+
@config ||= {}
|
34
|
+
end
|
35
|
+
|
36
|
+
# An array of path names for files that are candidates for being copied.
|
37
|
+
def file_candidates
|
38
|
+
@file_candidates ||= []
|
39
|
+
end
|
40
|
+
|
41
|
+
# Create a temporary directory to clone the repo into.
|
42
|
+
def clone_destination
|
43
|
+
@clone_destination ||= Dir.mktmpdir('chef-steel-')
|
44
|
+
end
|
45
|
+
|
46
|
+
# Look for and parse steel.yml.
|
47
|
+
# Supports a global and local config (in the repo).
|
48
|
+
# Order matters with latter configs' definitions overriding
|
49
|
+
# previous configs' values.
|
50
|
+
def parse_config
|
51
|
+
%w(/etc/steel/steel/yml steel.yml).each do |cfg|
|
52
|
+
if File.exist?(cfg)
|
53
|
+
begin
|
54
|
+
y = YAML.load_file(cfg)
|
55
|
+
rescue Psych::SyntaxError => e
|
56
|
+
error "[#{e.class}] Failed to parse '#{cfg}'!!"
|
57
|
+
error e.message
|
58
|
+
exit 1
|
59
|
+
end
|
60
|
+
# Merge the contents of the config into @config.
|
61
|
+
config.merge!(y)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Command line options.
|
67
|
+
def parse_options
|
68
|
+
Choice.options do
|
69
|
+
header ''
|
70
|
+
header 'Hone your tools!'
|
71
|
+
header ''
|
72
|
+
header 'Options:'
|
73
|
+
|
74
|
+
default_xfiles = %w(
|
75
|
+
.gitignore
|
76
|
+
Policyfile.rb
|
77
|
+
README.md
|
78
|
+
metadata.rb
|
79
|
+
)
|
80
|
+
option :exclude_files do
|
81
|
+
short '-e'
|
82
|
+
long '--exclude-files *XFILES' # Yeah, XFILES!
|
83
|
+
desc 'One or more explicit file names (space-separated) to *exclude* from being copied from the repo'
|
84
|
+
desc 'Ex. -e README.md'
|
85
|
+
desc 'Ex. --exclude-files README.md metadata.rb'
|
86
|
+
desc "Default: #{default_xfiles.to_s}"
|
87
|
+
default default_xfiles
|
88
|
+
end
|
89
|
+
|
90
|
+
option :files do
|
91
|
+
short '-f'
|
92
|
+
long '--files *FILES'
|
93
|
+
desc 'One or more explicit file names (space-separated) to copy from the repo'
|
94
|
+
desc 'Ex. -f .rubocop.yml'
|
95
|
+
desc 'Ex. --files .rubocop.yml .rspec'
|
96
|
+
desc 'Default: All top-level files in the repo (excluding the value if --exclude-files)'
|
97
|
+
end
|
98
|
+
|
99
|
+
option :repo do
|
100
|
+
short '-r'
|
101
|
+
long '--repo'
|
102
|
+
desc 'The full URL of a repo containing config files to clone'
|
103
|
+
end
|
104
|
+
|
105
|
+
option :version do
|
106
|
+
short '-v'
|
107
|
+
long '--version'
|
108
|
+
desc 'Show version and exit'
|
109
|
+
action do
|
110
|
+
puts "chef-steel v#{Chef::Steel::VERSION}"
|
111
|
+
exit
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
option :answer_yes do
|
116
|
+
short '-y'
|
117
|
+
long '--yes'
|
118
|
+
desc 'Answer "yes" to all prompts'
|
119
|
+
desc 'Default: false'
|
120
|
+
default false
|
121
|
+
end
|
122
|
+
|
123
|
+
footer ''
|
124
|
+
end
|
125
|
+
# Merge command line options on top of the config values.
|
126
|
+
# Command line option win. Every. Time.
|
127
|
+
config.merge!(Choice.choices)
|
128
|
+
end
|
129
|
+
|
130
|
+
# After we've parsed the config and command line options, let's
|
131
|
+
# ensure the final config includes a minimal set of options.
|
132
|
+
def validate_config
|
133
|
+
if config['repo'].nil? || !config['repo'].is_a?(String) || config['repo'].empty?
|
134
|
+
error "No 'repo' value found in 'steel.yml' or on the command line!"
|
135
|
+
error "Which repo would you like to pull files from?"
|
136
|
+
Choice.help
|
137
|
+
exit 2
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Locate potential files at the top of the directory.
|
142
|
+
# We won't traverse into any subdirectories.
|
143
|
+
# use Dir.glob rather than Find.find as the latter doesn't
|
144
|
+
# provide a native way to minimize depth (like the `find` command).
|
145
|
+
# File::FNM_DOTMATCH is handy flag that surfaces dotfiles.
|
146
|
+
def find_top_files(clone_destination)
|
147
|
+
globule = File.join(clone_destination, '*') # Define a variable here to the next line is legible.
|
148
|
+
Dir.glob(globule, File::FNM_DOTMATCH).each do |path|
|
149
|
+
next if File.directory?(path) # Should omit '.' and '..' as well.
|
150
|
+
next if config['exclude_files'].include? File.basename(path)
|
151
|
+
unless config['files'].nil? || config['files'].empty?
|
152
|
+
next unless config['files'].include? File.basename(path)
|
153
|
+
end
|
154
|
+
file_candidates << path
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Copy files from the cloned repo into this local repo.
|
159
|
+
def copy_files
|
160
|
+
file_candidates.each do |remote_file|
|
161
|
+
local_file = File.basename(remote_file)
|
162
|
+
if File.exist?(local_file)
|
163
|
+
if same_file?(local_file, remote_file)
|
164
|
+
info "\n>> '#{local_file}' has the same contents here as in the repo. Leaving it alone."
|
165
|
+
else
|
166
|
+
if config['answer_yes']
|
167
|
+
warn "\n>> '#{local_file}' is different than its counterpart in the repo."
|
168
|
+
info "Copying #{remote_file} to #{local_file}... (answer_yes is true)"
|
169
|
+
copy_file(remote_file, local_file)
|
170
|
+
else
|
171
|
+
warn "\n>> '#{local_file}' is different than its counterpart in the repo (see below)"
|
172
|
+
git_diff(local_file, remote_file)
|
173
|
+
prompt "\nDo you want to overwrite #{local_file} with the version from the repo? [y/N]: "
|
174
|
+
|
175
|
+
answer = $stdin.gets.chomp
|
176
|
+
case answer
|
177
|
+
when ''
|
178
|
+
error 'Moving on.' # Default behavior.
|
179
|
+
when /y/i
|
180
|
+
info "Copying #{remote_file} to #{local_file}..."
|
181
|
+
copy_file(remote_file, local_file)
|
182
|
+
when /n/i
|
183
|
+
error 'Moving on.'
|
184
|
+
else
|
185
|
+
error 'Unknown selection. Moving on.'
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
190
|
+
else
|
191
|
+
info "\n>> '#{local_file}' does not exist locally."
|
192
|
+
info "Copying #{remote_file} to #{local_file}..."
|
193
|
+
copy_file(remote_file, local_file)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def run
|
199
|
+
validate_in_repo
|
200
|
+
parse_config
|
201
|
+
parse_options
|
202
|
+
validate_config
|
203
|
+
|
204
|
+
# Do work, son.
|
205
|
+
repo = config['repo']
|
206
|
+
log "\nCloning #{repo} into #{clone_destination}..."
|
207
|
+
git_clone(repo, clone_destination)
|
208
|
+
find_top_files(clone_destination)
|
209
|
+
copy_files
|
210
|
+
clean_up(clone_destination)
|
211
|
+
info "\nAll done!"
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
data/steel.yml.example
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# chef-steel
|
2
|
+
# Define values that instruct steel what to do. These values can be overridden
|
3
|
+
# on the command line.
|
4
|
+
|
5
|
+
# Set 'repo' to the URL of a repository from which steel will clone and copy
|
6
|
+
# top-level files.
|
7
|
+
repo: git@github.com:RyanFrantz/chef-testing-configs.git
|
8
|
+
#repo: https://github.com/RyanFrantz/chef-testing-configs.git
|
9
|
+
|
10
|
+
# Set 'answer_yes' to true to perform any operation that steel would normally prompt for.
|
11
|
+
#answer_yes: true
|
12
|
+
|
13
|
+
# 'files' is a list of files that should explicitly be copied.
|
14
|
+
#files:
|
15
|
+
# - .rubocop.yml
|
16
|
+
# - Jenkinsfile
|
17
|
+
|
18
|
+
# 'exclude_files' is a list of files that should not be copied.
|
19
|
+
#exclude_files:
|
20
|
+
# - .gitignore
|
21
|
+
# - .rspec
|
metadata
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: chef-steel
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ryan Frantz
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-10-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: choice
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.2'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.2.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.2'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.2.0
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: colorize
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0.8'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 0.8.1
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0.8'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 0.8.1
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: rake
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '10.0'
|
60
|
+
type: :development
|
61
|
+
prerelease: false
|
62
|
+
version_requirements: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - "~>"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '10.0'
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: rspec
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '3.0'
|
74
|
+
type: :development
|
75
|
+
prerelease: false
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - "~>"
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '3.0'
|
81
|
+
description: |2
|
82
|
+
Hone your tools with chef-steel!
|
83
|
+
|
84
|
+
chef-steel is a tool that can keep testing-related configurations up-to-date
|
85
|
+
within one or more repos.
|
86
|
+
|
87
|
+
If you work within many different repos that share a common set of testing tools
|
88
|
+
(i.e. Rubocop, Foodcritic, Travis, Jenkins, etc.) it can be easy for their
|
89
|
+
configuration to drift. With chef-steel you can update one or more of these
|
90
|
+
configuration files from a central repository, as needed.
|
91
|
+
email:
|
92
|
+
- ryanleefrantz@gmail.com
|
93
|
+
executables:
|
94
|
+
- steel
|
95
|
+
extensions: []
|
96
|
+
extra_rdoc_files: []
|
97
|
+
files:
|
98
|
+
- ".gitignore"
|
99
|
+
- ".rspec"
|
100
|
+
- LICENSE.txt
|
101
|
+
- README.md
|
102
|
+
- Rakefile
|
103
|
+
- bin/steel
|
104
|
+
- chef-steel.gemspec
|
105
|
+
- lib/chef/steel.rb
|
106
|
+
- lib/chef/steel/exceptions.rb
|
107
|
+
- lib/chef/steel/filetools.rb
|
108
|
+
- lib/chef/steel/git.rb
|
109
|
+
- lib/chef/steel/logger.rb
|
110
|
+
- lib/chef/steel/runner.rb
|
111
|
+
- lib/chef/steel/version.rb
|
112
|
+
- steel.yml.example
|
113
|
+
homepage: https://github.com/RyanFrantz/chef-steel
|
114
|
+
licenses:
|
115
|
+
- MIT
|
116
|
+
metadata: {}
|
117
|
+
post_install_message:
|
118
|
+
rdoc_options: []
|
119
|
+
require_paths:
|
120
|
+
- lib
|
121
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '0'
|
131
|
+
requirements: []
|
132
|
+
rubyforge_project:
|
133
|
+
rubygems_version: 2.6.11
|
134
|
+
signing_key:
|
135
|
+
specification_version: 4
|
136
|
+
summary: A tool to keep testing-related configurations up-to-date
|
137
|
+
test_files: []
|