chef-relevant-tests 1.0.0
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
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4f5e163490693818aa4ea66b915c5d42fddfc96a
|
4
|
+
data.tar.gz: 22154e143b81e92dc60cc92040d61a09fb33e468
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 51095f24d9cced208329d1640737613b5a1e24e1814fec7f4278d3357b1af9055e0e1fc95d57e7ba49f6841eb437d44458fda7ecd94f60857bad1ac5c6ee8455
|
7
|
+
data.tar.gz: 2fa43a9bb328c9c5a12f9767e9695d9f624e21c9210c964ae9b82bf6880dd4c7c09c167e5c37da8561af845fa8a9b21beaede669d25f0b164832fa03c4f7dd93
|
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
3
|
+
require 'chef-relevant-tests'
|
4
|
+
|
5
|
+
begin
|
6
|
+
ChefRelevantTests::Cli.set_revision(ARGV[0])
|
7
|
+
ChefRelevantTests::Cli.set_expander(ARGV[1])
|
8
|
+
|
9
|
+
puts ChefRelevantTests::Cli.run.join(' ')
|
10
|
+
rescue => e
|
11
|
+
$stderr.puts(e.message)
|
12
|
+
$stderr.write(e.backtrace.join("\n"))
|
13
|
+
exit 1
|
14
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module ChefRelevantTests
|
2
|
+
module ChangeDetectors
|
3
|
+
class Berkshelf
|
4
|
+
def initialize(ref)
|
5
|
+
@ref = ref
|
6
|
+
end
|
7
|
+
|
8
|
+
def should_run?
|
9
|
+
load_dependencies
|
10
|
+
!!defined?(Berkshelf)
|
11
|
+
end
|
12
|
+
|
13
|
+
def changed_cookbooks
|
14
|
+
load_dependencies
|
15
|
+
|
16
|
+
changed_cookbooks = []
|
17
|
+
dependent_cookbooks = []
|
18
|
+
|
19
|
+
old, new = get_berksfiles_to_compare
|
20
|
+
|
21
|
+
# `old` and `new` are both in the format
|
22
|
+
# [["cookbook_name", "0.0.2"], ...]
|
23
|
+
#
|
24
|
+
# So, the changed cookbooks are the ones that appear in the new version but
|
25
|
+
# not the old version. This should also filter any cookbooks which no longer
|
26
|
+
# exist.
|
27
|
+
diff = berksfile_locked_versions(new) - berksfile_locked_versions(old)
|
28
|
+
|
29
|
+
changed_cookbooks = diff.map(&:first)
|
30
|
+
|
31
|
+
dependent_cookbooks = changed_cookbooks.map { |name| berksfile_dependent_upon(new, name) }.flatten
|
32
|
+
|
33
|
+
changed_cookbooks | dependent_cookbooks
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def load_dependencies
|
39
|
+
begin
|
40
|
+
require 'berkshelf'
|
41
|
+
rescue LoadError
|
42
|
+
return false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Separated for testability
|
47
|
+
def get_berksfiles_to_compare
|
48
|
+
Dir.mktmpdir do |dir|
|
49
|
+
`git show #{@ref}:Berksfile.lock > #{dir}/Berksfile.lock`
|
50
|
+
old = ::Berkshelf::Lockfile.from_file("#{dir}/Berksfile.lock")
|
51
|
+
new = ::Berkshelf::Lockfile.from_file('Berksfile.lock')
|
52
|
+
|
53
|
+
[old, new]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# The vertices in the Berkshelf-produced graph are the version-locked
|
58
|
+
# cookbooks (the part of the Berksfile.lock after "GRAPH")
|
59
|
+
#
|
60
|
+
# @param lockfile [Berkshelf::Lockfile] Lockfile to analyze
|
61
|
+
# @return [Array<Array>] for each locked cookbook, an array with two elements:
|
62
|
+
# first, cookbook name
|
63
|
+
# second, cookbook version
|
64
|
+
def berksfile_locked_versions(lockfile)
|
65
|
+
lockfile.graph.map { |g| [g.name, g.version] }
|
66
|
+
end
|
67
|
+
|
68
|
+
# Traverse the Berkshelf dependency graph to find any other cookbooks that
|
69
|
+
# include a dependency on the target cookbook.
|
70
|
+
#
|
71
|
+
# @param lockfile [Berkshelf::Lockfile]
|
72
|
+
# @param cookbook [String]
|
73
|
+
# @return [Array] Names of dependent cookbooks
|
74
|
+
def berksfile_dependent_upon(lockfile, cookbook)
|
75
|
+
lockfile.graph.select { |n| n.dependencies.include?(cookbook) }.map(&:name)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module ChefRelevantTests
|
4
|
+
class Cli
|
5
|
+
class << self
|
6
|
+
def set_revision(rev)
|
7
|
+
@@revision = rev
|
8
|
+
end
|
9
|
+
|
10
|
+
def set_expander(exp)
|
11
|
+
@@expander = exp
|
12
|
+
end
|
13
|
+
|
14
|
+
def run
|
15
|
+
changed_cookbooks = find_cookbook_diffs(@@revision)
|
16
|
+
|
17
|
+
EXPANDER_REGISTRY[@@expander]
|
18
|
+
.new(@@revision, changed_cookbooks)
|
19
|
+
.expand
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
CHANGE_DETECTOR_REGISTRY = [
|
25
|
+
ChefRelevantTests::ChangeDetectors::Berkshelf,
|
26
|
+
].freeze
|
27
|
+
|
28
|
+
EXPANDER_REGISTRY = {
|
29
|
+
'test-kitchen' => ChefRelevantTests::Expanders::TestKitchen,
|
30
|
+
}.freeze
|
31
|
+
|
32
|
+
def find_cookbook_diffs(rev)
|
33
|
+
enabled_change_detectors = CHANGE_DETECTOR_REGISTRY.map do |klass|
|
34
|
+
detector = klass.new(rev)
|
35
|
+
|
36
|
+
detector if detector.should_run?
|
37
|
+
end.compact
|
38
|
+
|
39
|
+
raise 'Unable to find changes - try `gem install berkshelf`.' if enabled_change_detectors.none?
|
40
|
+
|
41
|
+
enabled_change_detectors.each_with_object(Set.new) do |detector, cookbooks|
|
42
|
+
cookbooks.merge(detector.changed_cookbooks)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module ChefRelevantTests
|
2
|
+
module Expanders
|
3
|
+
class TestKitchen
|
4
|
+
def initialize(rev, changed_cookbooks = [])
|
5
|
+
@rev = rev
|
6
|
+
@changed_cookbooks = changed_cookbooks
|
7
|
+
end
|
8
|
+
|
9
|
+
def expand
|
10
|
+
require 'chef'
|
11
|
+
require 'chef/knife'
|
12
|
+
require 'kitchen'
|
13
|
+
|
14
|
+
changed_kitchen_instances | kitchen_run_lists.map do |instance_name, run_list|
|
15
|
+
instance_name if (@changed_cookbooks & expand_run_list(run_list)).any?
|
16
|
+
end.compact
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# Separated for testability
|
22
|
+
def get_kitchen_yml_to_compare
|
23
|
+
old = nil
|
24
|
+
new = nil
|
25
|
+
|
26
|
+
Dir.mktmpdir do |dir|
|
27
|
+
`git show #{@rev}:.kitchen.yml > #{dir}/.kitchen.yml`
|
28
|
+
|
29
|
+
old = kitchen_config("#{dir}/.kitchen.yml")
|
30
|
+
new = kitchen_config('.kitchen.yml')
|
31
|
+
end
|
32
|
+
|
33
|
+
[old, new]
|
34
|
+
end
|
35
|
+
|
36
|
+
def changed_kitchen_instances
|
37
|
+
old, new = get_kitchen_yml_to_compare
|
38
|
+
|
39
|
+
new.instances.keep_if do |instance|
|
40
|
+
old_instance = old.instances.detect { |old| old.name == instance.name }
|
41
|
+
|
42
|
+
!old_instance || instance.provisioner.config_keys.any? do |config_key|
|
43
|
+
instance.provisioner[config_key] != old_instance.provisioner[config_key]
|
44
|
+
end
|
45
|
+
end.map(&:name)
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [Hash<String, Array>] Mapping of test-kitchen suite name to the run
|
49
|
+
# list specified in .kitchen.yml.
|
50
|
+
def kitchen_run_lists
|
51
|
+
c = kitchen_config('.kitchen.yml')
|
52
|
+
|
53
|
+
Hash[c.instances.map { |i| [i.name, i.provisioner[:run_list]] }]
|
54
|
+
end
|
55
|
+
|
56
|
+
# Use Chef (and Knife configuration) to expand the run list in the .kitchen.yml
|
57
|
+
# into a list of cookbooks.
|
58
|
+
#
|
59
|
+
# @return [Array] Cookbooks that have recipes that will be run
|
60
|
+
def expand_run_list(run_list, environment = 'default')
|
61
|
+
Chef::Config.from_file(Chef::Knife.locate_config_file)
|
62
|
+
|
63
|
+
Chef::RunList.new(*run_list)
|
64
|
+
.expand(environment, 'disk')
|
65
|
+
.recipes
|
66
|
+
.map { |r| Chef::Recipe.parse_recipe_name(r) }
|
67
|
+
.map { |cookbook, _recipe| cookbook.to_s }
|
68
|
+
.uniq
|
69
|
+
end
|
70
|
+
|
71
|
+
def kitchen_config(kitchen_yml)
|
72
|
+
Kitchen::Config.new(loader: Kitchen::Loader::YAML.new(:local_config => kitchen_yml))
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: chef-relevant-tests
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brigade Engineering
|
8
|
+
- Tom Dooner
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-10-27 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: chef
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '11'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '11'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rspec
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '3'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '3'
|
42
|
+
description: Only run the Chef tests that you need to run
|
43
|
+
email:
|
44
|
+
- eng@brigade.com
|
45
|
+
- tom.dooner@brigade.com
|
46
|
+
executables:
|
47
|
+
- chef-relevant-tests
|
48
|
+
extensions: []
|
49
|
+
extra_rdoc_files: []
|
50
|
+
files:
|
51
|
+
- bin/chef-relevant-tests
|
52
|
+
- lib/chef-relevant-tests.rb
|
53
|
+
- lib/chef-relevant-tests/change-detectors/berkshelf.rb
|
54
|
+
- lib/chef-relevant-tests/cli.rb
|
55
|
+
- lib/chef-relevant-tests/expanders/test-kitchen.rb
|
56
|
+
homepage: https://github.com/brigade/chef-relevant-tests
|
57
|
+
licenses:
|
58
|
+
- MIT
|
59
|
+
metadata: {}
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.9.3
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
requirements: []
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 2.2.2
|
77
|
+
signing_key:
|
78
|
+
specification_version: 4
|
79
|
+
summary: Gem which looks at Chef configuration to narrow which tests you need to run
|
80
|
+
test_files: []
|