reagan 0.8.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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