reagan 0.8.2 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7eb97fa712f2fce7de36576bdf54675b9ce31096
4
- data.tar.gz: 516b0b9d1bae8c38a964361b8739f2a1c8301d2b
3
+ metadata.gz: 1cd896de4c2788114697c7ff8df89e864324d2b0
4
+ data.tar.gz: 59f8878ea5836ef1f887553a2c8bedd2e9abfd06
5
5
  SHA512:
6
- metadata.gz: da189f2e45bae76d189c552725361d81311c4681be7c67b5b9ac717615b796393bde0002adbbcd39e83b918d6c29af450930d72f89210911b67b2362d3655669
7
- data.tar.gz: 08cad4868acceff00afbf192b4a355c37f1c685be97391ade08e8ceab01335ddb78bf9d1ff61abe9477e66b271742e895e3c85761ffc724ab306fe1f48d760c3
6
+ metadata.gz: 13f87c4a768d237e634f8b1b556709b3d0c412d3e6f6d787870c37926d4cff43f175362de90428d1f4717357303545f6873a1f2d2f1f4e98d108943c4377170a
7
+ data.tar.gz: b6d4738eb02e1f04eea2a34b3fc95e5a8e9e70af97e1db37c36a07a1386013a80f5b8cacd2ec925bd5b3b3dd8650547635f181c5c49098d5d333f7cd8117e53c
@@ -1,24 +1,18 @@
1
- AllCops:
2
- Exclude:
3
- - vendor/**
4
-
5
- AlignParameters:
6
- Enabled: false
7
- CyclomaticComplexity:
8
- Enabled: false
9
- Encoding:
10
- Enabled: false
11
- HashSyntax:
1
+ AbcSize:
12
2
  Enabled: false
13
- LineLength:
3
+
4
+ Documentation:
14
5
  Enabled: false
6
+
15
7
  MethodLength:
16
8
  Enabled: false
17
- Metrics/AbcSize:
18
- Enabled: false
19
- NumericLiterals:
20
- Enabled: false
21
- SingleSpaceBeforeFirstArg:
9
+
10
+ LineLength:
22
11
  Enabled: false
12
+
23
13
  PerceivedComplexity:
24
14
  Enabled: false
15
+
16
+ CyclomaticComplexity:
17
+ Enabled: false
18
+
@@ -1,6 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.9.3
4
3
  - 2.1.5
5
4
  - 2.2.0
6
5
  script:
data/Gemfile CHANGED
@@ -1,10 +1,3 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'octokit', '~> 3.0'
4
- gem 'chef', '>= 11.0'
5
- gem 'ridley', '~> 4.0'
6
-
7
- group :test do
8
- gem 'rubocop', '~> 0.28.0'
9
- gem 'rake', '~> 10.0'
10
- end
3
+ gemspec
data/README.md CHANGED
@@ -30,12 +30,11 @@ While this app is written to be run as a Jenkins job it can also be run locally.
30
30
  ```ruby
31
31
  source 'https://rubygems.org'
32
32
 
33
- gem 'chef', '~> 11.0'
34
- gem 'berkshelf', '~> 3.2'
33
+ gem 'chef', '~> 12.3'
35
34
 
36
35
  group :test do
37
- gem 'reagan', '~> 0.6'
38
- gem 'rubocop', '~> 0.27'
36
+ gem 'reagan', '~> 0.8'
37
+ gem 'rubocop', '~> 0.30'
39
38
  gem 'foodcritic', '~> 4.0'
40
39
  end
41
40
  ```
data/bin/reagan CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # encoding: UTF-8
2
3
  #
3
4
  # Author:: Tim Smith (<tim@cozy.co>)
4
5
  # Copyright:: Copyright (c) 2015 Tim Smith
@@ -19,6 +20,6 @@
19
20
  # load the libs
20
21
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
21
22
 
22
- require 'application'
23
+ require 'reagan'
23
24
 
24
- Reagan::Application.new.run
25
+ Reagan.run
@@ -0,0 +1,35 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author:: Tim Smith (<tim@cozy.co>)
4
+ # Copyright:: Copyright (c) 2014-2015 Tim Smith
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ # add a simple method for making marquees
20
+ class String
21
+ def marquee
22
+ puts "\n#{self}"
23
+ length.times { printf '-' }
24
+ puts "\n"
25
+ end
26
+
27
+ def to_red
28
+ "\033[31m#{self}\033[0m"
29
+ end
30
+
31
+ def indent(double_space_count = 1)
32
+ double_space_count.times { insert(0, ' ') }
33
+ self
34
+ end
35
+ end
@@ -0,0 +1,82 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author:: Tim Smith (<tim@cozy.co>)
4
+ # Copyright:: Copyright (c) 2014-2015 Tim Smith
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ # main Reagan application to which gathers configs, determines changes, and runs tests
20
+ module Reagan
21
+ require 'core/ext/string'
22
+ require 'reagan/config'
23
+ require 'reagan/changeset'
24
+ require 'reagan/test_json'
25
+ require 'reagan/test_knife'
26
+ require 'reagan/test_reagan'
27
+ require 'reagan/test_version'
28
+
29
+ # exit with a friendly message if nothing we test has been changed
30
+ def self::check_empty_update
31
+ if ChangeSet.empty?
32
+ 'No objects to test. Exiting'.marquee
33
+ exit 0
34
+ end
35
+ end
36
+
37
+ # check and see if the -p flag was passed and if so print the config hash
38
+ def self::check_print_config
39
+ return unless Config.settings['flags']['print_config']
40
+ 'Current config file / CLI flag values'.marquee
41
+ Config.pretty_print
42
+ exit 0
43
+ end
44
+
45
+ # run tests on each changed cookbook
46
+ def self::run
47
+ check_print_config
48
+ check_empty_update
49
+
50
+ # print objects that will be tested
51
+ 'The following chef objects will be tested'.marquee
52
+ %w(cookbooks roles environments data_bags).each do |type|
53
+ unless ChangeSet.files[type].empty?
54
+ puts "#{type}:"
55
+ ChangeSet.files[type].each { |obj| puts ' ' + obj }
56
+ end
57
+ end
58
+
59
+ results = []
60
+ ChangeSet.files['cookbooks'].each do |cookbook|
61
+ "Testing cookbook #{cookbook}".marquee
62
+ results << Reagan::TestKnife.new(cookbook).test
63
+ results << Reagan::TestVersion.new(cookbook).test
64
+ results << Reagan::TestReagan.new(cookbook).test
65
+ end
66
+
67
+ %w(data_bags roles environments).each do |type|
68
+ ChangeSet.files[type].each do |file|
69
+ "Testing #{type} file #{file}".marquee
70
+ results << TestJSON.new(file).test
71
+ end
72
+ end
73
+
74
+ # print success or failure
75
+ failure = results.include?(false)
76
+ text = failure ? 'Reagan testing has failed' : 'All Reagan tests have suceeded'
77
+ text.to_red.marquee
78
+
79
+ # if any test failed then exit 1 so jenkins can pick up the failure
80
+ exit 1 if failure
81
+ end
82
+ end
@@ -1,7 +1,7 @@
1
1
  # encoding: UTF-8
2
2
  #
3
3
  # Author:: Tim Smith (<tim@cozy.co>)
4
- # Copyright:: Copyright (c) 2014 Tim Smith
4
+ # Copyright:: Copyright (c) 2014-2015 Tim Smith
5
5
  # License:: Apache License, Version 2.0
6
6
  #
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,7 +17,6 @@
17
17
  # limitations under the License.
18
18
 
19
19
  begin
20
- require 'rubygems'
21
20
  require 'octokit'
22
21
  rescue LoadError => e
23
22
  raise "Missing gem or lib #{e}"
@@ -25,32 +24,40 @@ end
25
24
 
26
25
  module Reagan
27
26
  # determines changed files in the commit
28
- class Change < Application
29
- attr_accessor :files
30
- def initialize
31
- @config = Reagan::Change.config
32
- @files = changed_files
27
+ class ChangeSet
28
+ def self::files
29
+ @files ||= changed_files
33
30
  end
34
31
 
35
32
  # return hash of chef objects that have been changed
36
- def changed_files
37
- if @config['flags']['override_cookbooks']
33
+ def self::changed_files
34
+ if Config.settings['flags']['override_cookbooks']
38
35
  files_from_override
39
36
  else
40
- pull = pull_num
37
+ pull = Config.settings['flags']['pull']
41
38
  puts "Grabbing contents of pull request #{pull}\n"
42
39
  hash_builder(query_gh(pull))
43
40
  end
44
41
  end
45
42
 
43
+ # check if the changeset is empty
44
+ def self::empty?
45
+ objects_updated = false
46
+ %w(cookbooks roles environments data_bags).each do |object|
47
+ objects_updated = true unless files[object].empty?
48
+ puts files
49
+ end
50
+ !objects_updated
51
+ end
52
+
46
53
  # build a files hash based on the override cookbooks passed by the user
47
- def files_from_override
54
+ def self::files_from_override
48
55
  files = {}
49
56
  %w(environments roles data_bags).each { |object| files[object] = {} }
50
57
 
51
58
  # ensure that the passed cookbooks exist in the workspace first
52
59
  cookbooks = []
53
- @config['flags']['override_cookbooks'] .each do |cb|
60
+ Config.settings['flags']['override_cookbooks'].each do |cb|
54
61
  if object_still_exists(::File.join('cookbooks/', cb))
55
62
  cookbooks << cb
56
63
  else
@@ -62,29 +69,19 @@ module Reagan
62
69
  files
63
70
  end
64
71
 
65
- # fetch pull num from either ENV or CLI param
66
- def pull_num
67
- if @config['flags']['pull']
68
- pull = @config['flags']['pull']
69
- elsif ENV['ghprbPullId']
70
- pull = ENV['ghprbPullId']
71
- else
72
- puts 'Jenkins ghprbPullId environmental variable not set or --pull option not used. Cannot continue'
73
- exit 1
74
- end
75
- pull
76
- end
77
-
78
72
  # queries github for the files that have changed
79
- def query_gh(pull_num)
73
+ def self::query_gh(pull_num)
80
74
  Octokit.auto_paginate = true # avoids issues with large commits
81
- Octokit.api_endpoint = @config['github']['api_endpoint'] || 'https://api.github.com'
82
- gh = Octokit::Client.new(:access_token => @config['github']['auth_token'])
83
- files_from_pull(gh.pull_request_files(@config ['github']['repo'], pull_num))
75
+ Octokit.api_endpoint = Config.settings['github']['api_endpoint'] || 'https://api.github.com'
76
+ gh = Octokit::Client.new(access_token: Config.settings['github']['auth_token'])
77
+ files_from_pull(gh.pull_request_files(Config.settings['github']['repo'], pull_num))
78
+ rescue
79
+ puts 'Failed to query pull request contents from Github. Check the api_endpoint, repo, and token.'
80
+ exit 1
84
81
  end
85
82
 
86
83
  # convert pull request response to array of changed files
87
- def files_from_pull(pull_changes)
84
+ def self::files_from_pull(pull_changes)
88
85
  files = []
89
86
  pull_changes.each do |file|
90
87
  files << file[:filename]
@@ -93,12 +90,12 @@ module Reagan
93
90
  end
94
91
 
95
92
  # check to see if the file exists in the workspace so we don't test deleted objects
96
- def object_still_exists(file)
97
- ::File.exist?(::File.join(@config['jenkins']['workspace_dir'], file))
93
+ def self::object_still_exists(file)
94
+ ::File.exist?(::File.join(Config.settings['jenkins']['workspace_dir'], file))
98
95
  end
99
96
 
100
97
  # builds a hash of files / cookbooks that changed based on the pull data from GH
101
- def hash_builder(pull_files)
98
+ def self::hash_builder(pull_files)
102
99
  files = {}
103
100
  %w(environments roles data_bags cookbooks).each { |object| files[object] = [] }
104
101
  cookbooks = []
@@ -0,0 +1,139 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author:: Tim Smith (<tim@cozy.co>)
4
+ # Copyright:: Copyright (c) 2014-2015 Tim Smith
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ begin
20
+ require 'yaml'
21
+ require 'optparse'
22
+ rescue LoadError => e
23
+ raise "Missing gem or lib #{e}"
24
+ end
25
+
26
+ module Reagan
27
+ # builds a single config from passed flags, yaml config, and knife.rb
28
+ class Config
29
+ # lazy load config settings
30
+ def self::settings
31
+ @settings ||= merge_config
32
+ end
33
+
34
+ # pretty print the config hash
35
+ def self::pretty_print(hash = nil, spaces = 0)
36
+ hash = @settings if hash.nil?
37
+ hash.each do |k, v|
38
+ spaces.times { print ' ' }
39
+ print k.to_s + ': '
40
+ if v.class == Hash
41
+ print "\n"
42
+ pretty_print(v, spaces + 2)
43
+ else
44
+ puts v
45
+ end
46
+ end
47
+ end
48
+
49
+ # grabs the flags passed in via command line
50
+ def self::cli_flags
51
+ if @cli_flags
52
+ @cli_flags
53
+ else
54
+ flags = { 'config' => '/etc/reagan.yml' }
55
+ OptionParser.new do |opts|
56
+ opts.banner = 'Usage: reagan [options]'
57
+ opts.on('-o', '--override cb1,cb2', Array, 'Comma separated list of cookbooks to test') do |cookbooks|
58
+ flags[:override_cookbooks] = cookbooks
59
+ end
60
+
61
+ opts.on('-p', '--print', 'Print the config options that will be used') do |config|
62
+ flags['print_config'] = config
63
+ end
64
+
65
+ opts.on('-p', '--pull_num 123', Integer, 'Github pull number to test') do |pull|
66
+ flags['pull'] = pull
67
+ end
68
+
69
+ opts.on('-c', '--config reagan.yml', 'Path to config file (defaults to /etc/reagan.yml)') do |config|
70
+ flags['config'] = config
71
+ end
72
+
73
+ opts.on('-h', '--help', 'Displays Help') do
74
+ puts opts
75
+ exit
76
+ end
77
+ end.parse!
78
+
79
+ @cli_flags = flags
80
+ flags
81
+ end
82
+ end
83
+
84
+ # loads the reagan.yml config file from /etc/reagan.yml or the passed location
85
+ def self::config_file
86
+ config = YAML.load_file(cli_flags['config'])
87
+
88
+ config
89
+ rescue Errno::ENOENT
90
+ puts "ERROR: Cannot load Reagan config file at #{cli_flags['config']}".to_red
91
+ exit 1
92
+ rescue Psych::SyntaxError
93
+ puts "ERROR: Syntax error in Reagan config file at #{cli_flags['config']}".to_red
94
+ exit 1
95
+ end
96
+
97
+ # make sure the config was properly loaded and contains the various keys we need
98
+ def self::validate
99
+ settings = Config.Settings
100
+
101
+ if settings == false
102
+ puts "ERROR: Reagan config at #{cli_flags['config']} does not contain any configuration data".to_red
103
+ exit 1
104
+ end
105
+
106
+ # make sure a pull request is specified
107
+ unless settings['flags']['pull']
108
+ puts 'Jenkins ghprbPullId environmental variable not set or --pull option not used. Cannot continue'
109
+ exit 1
110
+ end
111
+
112
+ # if workstation not defined in the config file try to use the Jenkins workspace variable
113
+ unless settings['jenkins'] && loaded_file['jenkins']['workspace_dir']
114
+ workspace = ENV['WORKSPACE']
115
+ if workspace
116
+ settings['jenkins'] = {}
117
+ settings['jenkins']['workspace_dir'] = workspace
118
+ else
119
+ puts 'Jenkins workspace_dir not defined in the config file and $WORKSPACE env variable empty. Exiting'.to_red
120
+ exit
121
+ end
122
+ end
123
+ end
124
+
125
+ # join the config file with the passed flags into a single object
126
+ def self::merge_config
127
+ config = config_file
128
+ config['flags'] = {}
129
+ config['flags'].merge!(cli_flags)
130
+
131
+ # if no pull request provided at the CLI use the Jenkins environmental variable
132
+ unless config['flags']['pull']
133
+ config['flags']['pull'] = ENV['ghprbPullId']
134
+ end
135
+
136
+ config
137
+ end
138
+ end
139
+ end
@@ -16,17 +16,12 @@
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
18
 
19
- begin
20
- require 'json'
21
- rescue LoadError => e
22
- raise "Missing gem or lib #{e}"
23
- end
19
+ require 'json'
24
20
 
25
21
  module Reagan
26
22
  # tests to make sure the version has been updated on the cookbook
27
- class TestJSON < Application
23
+ class TestJSON
28
24
  def initialize(file)
29
- @config = Reagan::TestJSON.config
30
25
  @file = file
31
26
  end
32
27
 
@@ -35,13 +30,13 @@ module Reagan
35
30
  def test
36
31
  puts 'Running JSON parsing test:'
37
32
  begin
38
- json_file = File.read(File.join(@config['jenkins']['workspace_dir'], @file))
33
+ json_file = File.read(File.join(Config.settings['jenkins']['workspace_dir'], @file))
39
34
  JSON.parse(json_file)
40
35
  success = true
41
36
  rescue JSON::JSONError
42
37
  success = false
43
38
  end
44
- puts success ? ' PASS: JSON parses' : ' FAIL: JSON does NOT parse'
39
+ puts success ? 'PASS: JSON parses'.indent : 'FAIL: JSON does NOT parse'.indent
45
40
  success
46
41
  end
47
42
  end
@@ -18,9 +18,8 @@
18
18
 
19
19
  module Reagan
20
20
  # tests cookbooks using knife cookbook test functionality
21
- class TestKnife < Application
21
+ class TestKnife
22
22
  def initialize(cookbook)
23
- @config = Reagan::TestKnife.config
24
23
  @cookbook = cookbook
25
24
  end
26
25
 
@@ -28,10 +27,10 @@ module Reagan
28
27
  # returns true if cookbook passed or false if it failed
29
28
  def test
30
29
  # grab the version of the cookbook in the local metadata
31
- result = system "knife cookbook test -o #{File.join(@@config['jenkins']['workspace_dir'], 'cookbooks')} #{@cookbook} > /dev/null 2>&1"
30
+ result = system "knife cookbook test -o #{File.join(Config.settings['jenkins']['workspace_dir'], 'cookbooks')} #{@cookbook} > /dev/null 2>&1"
32
31
 
33
32
  puts 'Running knife cookbook test:'
34
- puts result ? ' PASS: Knife cookbook test was successful' : ' FAIL: Knife cookbookk test was NOT successful'
33
+ puts result ? 'PASS: Knife cookbook test was successful'.indent : 'FAIL: Knife cookbookk test was NOT successful'.indent
35
34
  result
36
35
  end
37
36
  end
@@ -18,9 +18,8 @@
18
18
 
19
19
  module Reagan
20
20
  # tests cookbooks using tests defined in reagan_test.yml files
21
- class TestReagan < Application
21
+ class TestReagan
22
22
  def initialize(cookbook)
23
- @config = Reagan::TestReagan.config
24
23
  @cookbook = cookbook
25
24
  end
26
25
 
@@ -28,13 +27,13 @@ module Reagan
28
27
  def test
29
28
  puts 'Running reagan_test.yml defined tests:'
30
29
  # check to see if a reagan_test.yml file exists
31
- if File.exist?(File.join(@config['jenkins']['workspace_dir'], 'cookbooks', @cookbook, 'reagan_test.yml'))
30
+ if File.exist?(File.join(Config.settings['jenkins']['workspace_dir'], 'cookbooks', @cookbook, 'reagan_test.yml'))
32
31
 
33
32
  # load the reagan config file
34
- reagan_def = YAML.load_file(File.join(@config['jenkins']['workspace_dir'], 'cookbooks', @cookbook, 'reagan_test.yml'))
33
+ reagan_def = YAML.load_file(File.join(Config.settings['jenkins']['workspace_dir'], 'cookbooks', @cookbook, 'reagan_test.yml'))
35
34
 
36
35
  # change into the cookbook dir so rake tests run locally
37
- Dir.chdir(File.join(@config['jenkins']['workspace_dir'], 'cookbooks', @cookbook))
36
+ Dir.chdir(File.join(Config.settings['jenkins']['workspace_dir'], 'cookbooks', @cookbook))
38
37
 
39
38
  status = true
40
39
  reagan_def['tests'].each do |test|
@@ -42,10 +41,10 @@ module Reagan
42
41
  result = system test
43
42
  status = false if result == false
44
43
  end
45
- puts status ? ' PASS: reagan_test.yml test was successful' : ' FAIL: reagan_test.yml test was NOT successful'
44
+ puts status ? 'PASS: reagan_test.yml test was successful' : ' FAIL: reagan_test.yml test was NOT successful'.indent
46
45
  status
47
46
  else
48
- puts ' SKIP: No reagan_test.yml file found in the cookbook path. Skipping test'
47
+ puts 'SKIP: No reagan_test.yml file found in the cookbook path. Skipping test'.indent
49
48
  status
50
49
  end
51
50
  end
@@ -17,7 +17,6 @@
17
17
  # limitations under the License.
18
18
 
19
19
  begin
20
- require 'rubygems'
21
20
  require 'ridley'
22
21
  require 'chef/cookbook/metadata'
23
22
  rescue LoadError => e
@@ -26,16 +25,15 @@ end
26
25
 
27
26
  module Reagan
28
27
  # tests to make sure the version has been updated on the cookbook
29
- class TestVersion < Application
28
+ class TestVersion
30
29
  def initialize(cookbook)
31
- @config = Reagan::TestVersion.config
32
30
  @cookbook = cookbook
33
31
  end
34
32
 
35
33
  # grab the version of the cookbook in the local metadata
36
34
  def check_commit_version
37
35
  metadata = Chef::Cookbook::Metadata.new
38
- metadata.from_file(File.join(@config['jenkins']['workspace_dir'], 'cookbooks', @cookbook, 'metadata.rb'))
36
+ metadata.from_file(File.join(Config.settings['jenkins']['workspace_dir'], 'cookbooks', @cookbook, 'metadata.rb'))
39
37
  metadata.version
40
38
  end
41
39
 
@@ -44,11 +42,11 @@ module Reagan
44
42
  Ridley::Logging.logger.level = Logger.const_get 'ERROR'
45
43
  begin
46
44
  server_con = Ridley.new(
47
- server_url: @config['chef']['server_url'],
48
- client_name: @config['chef']['client_name'],
49
- client_key: @config['chef']['pem_path'],
50
- ssl: { verify: false }
51
- )
45
+ server_url: Config.settings['chef']['server_url'],
46
+ client_name: Config.settings['chef']['client_name'],
47
+ client_key: Config.settings['chef']['pem_path'],
48
+ ssl: { verify: false }
49
+ )
52
50
  # return the version if the cookbook exists or return 0.0.0 if it's a new coobook not yet on the server
53
51
  if server_con.cookbook.all[@cookbook]
54
52
  server_con.cookbook.all[@cookbook][0]
@@ -56,7 +54,7 @@ module Reagan
56
54
  '0.0.0'
57
55
  end
58
56
  rescue Ridley::Errors::ConnectionFailed
59
- puts ' ERROR: Failed to connect to the Chef server. Cannot continue'
57
+ puts ' ERROR: Failed to connect to the Chef server. Cannot continue'.to_red
60
58
  exit 1
61
59
  end
62
60
  end
@@ -69,9 +67,9 @@ module Reagan
69
67
  updated = Gem::Version.new(serv_v) < Gem::Version.new(commit_v) ? true : false
70
68
 
71
69
  puts "Running cookbook version rev'd test:"
72
- puts " Server version: #{serv_v}"
73
- puts " Commit version: #{commit_v}"
74
- puts updated ? " PASS: Metadata version has been rev'd" : " FAIL: Metadata version has NOT been rev'd"
70
+ puts "Server version: #{serv_v}".indent
71
+ puts "Commit version: #{commit_v}".indent
72
+ puts updated ? "PASS: Metadata version has been rev'd".indent : "FAIL: Metadata version has NOT been rev'd".indent
75
73
  updated
76
74
  end
77
75
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'reagan'
3
- s.version = '0.8.2'
3
+ s.version = '1.0.0'
4
4
  s.date = Date.today.to_s
5
5
  s.platform = Gem::Platform::RUBY
6
6
  s.extra_rdoc_files = ['README.md', 'LICENSE']
@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
16
16
  s.add_dependency 'chef', '>= 11.0'
17
17
  s.add_dependency 'ridley', '~> 4.0'
18
18
  s.add_development_dependency 'rake', '~> 10.0'
19
- s.add_development_dependency 'rubocop', '~> 0.28.0'
19
+ s.add_development_dependency 'rubocop', '~> 0.30.1'
20
20
 
21
21
  s.files = `git ls-files -z`.split("\x0")
22
22
  s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reagan
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Smith
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-03 00:00:00.000000000 Z
11
+ date: 2015-04-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: octokit
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - ~>
74
74
  - !ruby/object:Gem::Version
75
- version: 0.28.0
75
+ version: 0.30.1
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - ~>
81
81
  - !ruby/object:Gem::Version
82
- version: 0.28.0
82
+ version: 0.30.1
83
83
  description: Trust But Verify - Ruby build script for Jenkins that automates the testing
84
84
  of Chef cookbooks
85
85
  email: tim@cozy.co
@@ -97,13 +97,14 @@ files:
97
97
  - README.md
98
98
  - Rakefile
99
99
  - bin/reagan
100
- - lib/application.rb
101
- - lib/change.rb
102
- - lib/config.rb
103
- - lib/test_json.rb
104
- - lib/test_knife.rb
105
- - lib/test_reagan.rb
106
- - lib/test_version.rb
100
+ - lib/core/ext/string.rb
101
+ - lib/reagan.rb
102
+ - lib/reagan/changeset.rb
103
+ - lib/reagan/config.rb
104
+ - lib/reagan/test_json.rb
105
+ - lib/reagan/test_knife.rb
106
+ - lib/reagan/test_reagan.rb
107
+ - lib/reagan/test_version.rb
107
108
  - reagan.gemspec
108
109
  - reagan.yml.EXAMPLE
109
110
  - reagan_test.yml.EXAMPLE
@@ -1,105 +0,0 @@
1
- # encoding: UTF-8
2
- #
3
- # Author:: Tim Smith (<tim@cozy.co>)
4
- # Copyright:: Copyright (c) 2014 Tim Smith
5
- # License:: Apache License, Version 2.0
6
- #
7
- # Licensed under the Apache License, Version 2.0 (the "License");
8
- # you may not use this file except in compliance with the License.
9
- # You may obtain a copy of the License at
10
- #
11
- # http://www.apache.org/licenses/LICENSE-2.0
12
- #
13
- # Unless required by applicable law or agreed to in writing, software
14
- # distributed under the License is distributed on an "AS IS" BASIS,
15
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- # See the License for the specific language governing permissions and
17
- # limitations under the License.
18
-
19
- module Reagan
20
- # the main class for the reagan app. gets called by the reagan bin
21
- class Application
22
- require 'config'
23
- require 'change'
24
- require 'test_json'
25
- require 'test_knife'
26
- require 'test_reagan'
27
- require 'test_version'
28
-
29
- def initialize
30
- @config_obj = Reagan::Config.new
31
- @@config = @config_obj.settings
32
- @changes = Reagan::Change.new.files
33
- end
34
-
35
- def self.config
36
- @@config
37
- end
38
-
39
- # nicely prints marques
40
- def pretty_print(string)
41
- puts "\n#{string}"
42
- string.length.times { printf '-' }
43
- puts "\n"
44
- end
45
-
46
- # exit with a friendly message if nothing we test has been changed
47
- def check_empty_update
48
- objects_updated = false
49
- %w(cookbooks roles environments data_bags).each do |object|
50
- objects_updated = true unless @changes[object].empty?
51
- end
52
-
53
- unless objects_updated
54
- pretty_print('No objects to test. Exiting')
55
- exit 0
56
- end
57
- end
58
-
59
- # check and see if the -p flag was passed and if so print the config hash
60
- def check_print_config
61
- return unless @@config['flags']['print_config']
62
- pretty_print('Current config file / CLI flag values')
63
- @config_obj.print_config
64
- exit 0
65
- end
66
-
67
- # run tests on each changed cookbook
68
- def run
69
- check_print_config
70
- check_empty_update
71
-
72
- # print objects that will be tested
73
- pretty_print('The following chef objects will be tested')
74
- %w(cookbooks roles environments data_bags).each do |type|
75
- unless @changes[type].empty?
76
- puts "#{type}:"
77
- @changes[type].each { |obj| puts ' ' + obj }
78
- end
79
- end
80
-
81
- results = []
82
- @changes['cookbooks'].each do |cookbook|
83
- pretty_print("Testing cookbook #{cookbook}")
84
- results << Reagan::TestKnife.new(cookbook).test
85
- results << Reagan::TestVersion.new(cookbook).test
86
- results << Reagan::TestReagan.new(cookbook).test
87
- end
88
-
89
- %w(data_bags roles environments).each do |type|
90
- @changes[type].each do |file|
91
- pretty_print("Testing #{type} file #{file}")
92
- results << TestJSON.new(file).test
93
- end
94
- end
95
-
96
- # print success or failure
97
- failure = results.include?(false)
98
- text = failure ? 'Reagan testing has failed' : 'All Reagan tests have suceeded'
99
- pretty_print(text)
100
-
101
- # if any test failed then exit 1 so jenkins can pick up the failure
102
- exit 1 if failure
103
- end
104
- end
105
- end
@@ -1,118 +0,0 @@
1
- # encoding: UTF-8
2
- #
3
- # Author:: Tim Smith (<tim@cozy.co>)
4
- # Copyright:: Copyright (c) 2014 Tim Smith
5
- # License:: Apache License, Version 2.0
6
- #
7
- # Licensed under the Apache License, Version 2.0 (the "License");
8
- # you may not use this file except in compliance with the License.
9
- # You may obtain a copy of the License at
10
- #
11
- # http://www.apache.org/licenses/LICENSE-2.0
12
- #
13
- # Unless required by applicable law or agreed to in writing, software
14
- # distributed under the License is distributed on an "AS IS" BASIS,
15
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- # See the License for the specific language governing permissions and
17
- # limitations under the License.
18
-
19
- begin
20
- require 'yaml'
21
- require 'optparse'
22
- rescue LoadError => e
23
- raise "Missing gem or lib #{e}"
24
- end
25
-
26
- module Reagan
27
- # builds a single config from passed flags, yaml config, and knife.rb
28
- class Config
29
- attr_accessor :settings
30
- def initialize
31
- @flags = flag_parser
32
- @config_file = load_config_file
33
- @settings = build_config
34
- end
35
-
36
- # grabs the flags passed in via command line
37
- def flag_parser
38
- flags = { :pull => nil, :override_cookbooks => nil, :config => '/etc/reagan.yml', :print_config => false }
39
- OptionParser.new do |opts|
40
- opts.banner = 'Usage: reagan [options]'
41
- opts.on('-o', '--override cb1,cb2', Array, 'Comma separated list of cookbooks to test') do |cookbooks|
42
- flags[:override_cookbooks] = cookbooks
43
- end
44
-
45
- opts.on('-p', '--print', 'Print the config options that will be used') do |config|
46
- flags[:print_config] = config
47
- end
48
-
49
- opts.on('-p', '--pull_num 123', Integer, 'Github pull number to test') do |pull|
50
- flags[:pull] = pull
51
- end
52
-
53
- opts.on('-c', '--config reagan.yml', 'Path to config file (defaults to /etc/reagan.yml)') do |config|
54
- flags[:config] = config
55
- end
56
-
57
- opts.on('-h', '--help', 'Displays Help') do
58
- puts opts
59
- exit
60
- end
61
- end.parse!
62
-
63
- flags
64
- end
65
-
66
- # loads the reagan.yml config file from /etc/reagan.yml or the passed location
67
- def load_config_file
68
- config = YAML.load_file(@flags[:config])
69
- if config == false
70
- puts "ERROR: Reagan config at #{@flags[:config]} does not contain any configuration data"
71
- exit 1
72
- end
73
-
74
- # if not workstation was set try to use the Jenkins workspace variable
75
- unless config['jenkins'] && config['jenkins']['workspace_dir']
76
- workspace = ENV['WORKSPACE']
77
- if workspace
78
- config['jenkins'] = {}
79
- config['jenkins']['workspace_dir'] = workspace
80
- else
81
- puts 'Jenkins workspace not defined and $WORKSPACE empty. Exiting'
82
- exit
83
- end
84
- end
85
-
86
- config
87
- rescue Errno::ENOENT
88
- puts "ERROR: Cannot load Reagan config file at #{@flags[:config]}"
89
- exit 1
90
- rescue Psych::SyntaxError
91
- puts "ERROR: Syntax error in Reagan config file at #{@flags[:config]}"
92
- exit 1
93
- end
94
-
95
- # join the config file with the passed flags into a single object
96
- def build_config
97
- config = @config_file
98
- config['flags'] = {}
99
- @flags.each { |k, v| config['flags'][k.to_s] = v }
100
- config
101
- end
102
-
103
- # pretty print the config hash
104
- def print_config(hash = nil, spaces = 0)
105
- hash = @settings if hash.nil?
106
- hash.each do |k, v|
107
- spaces.times { print ' ' }
108
- print k.to_s + ': '
109
- if v.class == Hash
110
- print "\n"
111
- print_config(v, spaces + 2)
112
- else
113
- puts v
114
- end
115
- end
116
- end
117
- end
118
- end