puppet-ci-testing 0.11.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 60a555bfc11e077ffc1a8f8f4baee3c22f350e70
4
+ data.tar.gz: e65edadaf0ca0b8bb538c196902d6e31b52cfd5d
5
+ SHA512:
6
+ metadata.gz: 52f0cd8ff310dc0fb4de9c64aef6b1da62dee02b90a38fd7ee26bf4815d4391a194a92cdea5fbfd01e9f315a8719969c20c9ce46f432663aeebececa5b9974d5
7
+ data.tar.gz: f55079f2a88fc62fed7a01a510bbab6774eb50da39c1241b4306769693c8dfd51d9bf2f506c5220b7c06a80bcee3ed3093af1a7b67ddb11e4d6b42f8ab7d724f
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'fileutils'
5
+ require 'colorize'
6
+
7
+ require 'check_file_syntax'
8
+ require 'simple_junit'
9
+
10
+
11
+
12
+ def repo_directory
13
+ `git rev-parse --show-toplevel`.chomp
14
+ end
15
+
16
+
17
+ def changed_files
18
+ `git diff --cached --name-only --diff-filter=ACM`.split("\n")
19
+ end
20
+
21
+
22
+
23
+ options = { :excludes => [],
24
+ :directory => '.',
25
+ :junit => nil,
26
+ :display_stdout => true,
27
+ :git_hook => false,
28
+ }
29
+ OptionParser.new do |opts|
30
+ opts.banner = <<-EOH
31
+ Usage: #{File.basename $0} [options] [working dir]
32
+
33
+ Check the syntax of the following file types from the specified working
34
+ directory. If the working directory is not specified, then the current
35
+ working directory is used.
36
+
37
+ Supported file types: #{(CheckFileSyntax::ALL_CHECKS.each {|t| t.to_s}).join(', ')}
38
+
39
+ Options:
40
+ EOH
41
+
42
+ opts.on('--no-color', '-C', 'Disable text color') do
43
+ String.disable_colorization
44
+ end
45
+
46
+ opts.on('--exclude DIR', '-x', 'Exclude directory from any syntax checks') do |dir|
47
+ options[:excludes] << dir
48
+ end
49
+
50
+ opts.on('--junit DIR', '-j', 'Generate JUnit reports and deposit in DIR') do |dir|
51
+ options[:junit] = dir
52
+ end
53
+
54
+ opts.on('--no-output', '-n', 'Squelch the results on stdout (default to display)') do
55
+ options[:display_stdout] = false
56
+ end
57
+
58
+ opts.on('--git-hook', '-g', 'Execute as a Git pre-commit hook') do
59
+ options[:git_hook] = true
60
+ end
61
+ end.parse!
62
+
63
+ # check for an optional directory to
64
+ if ARGV.count == 1
65
+ options[:directory] = ARGV[0]
66
+ end
67
+
68
+ test_collection = SimpleJUnit::TestSuiteCollection.instance
69
+ test_suite = test_collection.create_testsuite('Syntax Checks')
70
+
71
+ if options[:git_hook]
72
+ deny_commit = false
73
+ changed_files.each do |changed|
74
+ CheckFileSyntax::check_file_syntax(changed) do |path, status, errors|
75
+ if status == :failed
76
+ deny_commit = true
77
+ end
78
+ CheckFileSyntax::show_status(path, status, errors)
79
+ end
80
+ end
81
+ exit(1) if deny_commit
82
+ else
83
+ CheckFileSyntax.search_all_files_for_errors(options[:directory], options[:excludes]) do |path, status, output|
84
+ unless status.nil?
85
+ tc = test_suite.create_testcase('File syntax', path)
86
+ case status
87
+ when :passed
88
+ tc.passed(output: output)
89
+ when :failed
90
+ tc.failed(type: 'syntax_error', output: '', error: output)
91
+ when :skipped
92
+ tc.skipped
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ if options[:junit]
99
+ unless Dir.exists? options[:junit]
100
+ FileUtils.mkdir_p options[:junit]
101
+ FileUtils.chmod 0755, options[:junit]
102
+ end
103
+ File.open("#{options[:junit]}/check_file_syntax-#{$$}.xml", 'w') do |fh|
104
+ fh.write test_collection.to_s
105
+ end
106
+ end
107
+
108
+ if options[:display_stdout]
109
+ test_suite.testcases.each do |tc|
110
+ CheckFileSyntax.show_status(tc.description, tc.status, tc.errors)
111
+ end
112
+ end
113
+
@@ -0,0 +1,253 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'ostruct'
5
+ require 'yaml'
6
+
7
+ require 'rake'
8
+ require 'rspec/core/rake_task'
9
+ require 'puppetlabs_spec_helper/rake_tasks'
10
+ require 'puppet-lint/tasks/puppet-lint'
11
+
12
+ require 'puppet-lint'
13
+
14
+ require 'check_file_syntax'
15
+
16
+
17
+ PUPPET_DIRS = ['files', 'lib', 'manifest', 'spec', 'templates', 'tests',
18
+ '.git_hooks']
19
+
20
+
21
+ def process_syntax_checks(opts)
22
+ # collect all the current directories
23
+ dirs = Dir.entries('.').select {|item| File.directory? item and item !~ /^\.{1,2}$/}
24
+
25
+ # calculate what will be excluded and what will be checked
26
+ exclude_dirs = opts.syntax_exclude_dirs || dirs - (dirs - PUPPET_DIRS)
27
+ checked_dirs = (dirs - PUPPET_DIRS) - exclude_dirs
28
+
29
+ puts <<-EOM
30
+ ========================================================================
31
+ ========================================================================
32
+
33
+ Performaning syntax checks
34
+
35
+ File types: #{opts.syntax_checks.map {|i| i.to_s}.join(', ')}
36
+ Directories: #{checked_dirs.join(', ')}
37
+
38
+ ************************************************************************
39
+
40
+ EOM
41
+
42
+ num = CheckFileSyntax.search_all_files_for_errors('.', excludes=exclude_dirs,
43
+ checks=opts.syntax_checks)
44
+
45
+ if num > 0
46
+ puts <<-EOM
47
+
48
+ ************************************************************************
49
+
50
+ Failed syntax checks: #{num}
51
+
52
+ THESE CHECKS MUST PASS TO COMPLETE BUILD.
53
+
54
+ ************************************************************************
55
+
56
+ EOM
57
+ return false
58
+ end
59
+ return true
60
+ end
61
+
62
+
63
+ def process_lint_parsing(opts)
64
+
65
+ all_checks = PuppetLint.configuration.checks.map {|chk| chk.to_s}
66
+ enables = opts.lint_enable || all_checks
67
+ disables = all_checks - enables
68
+
69
+ puts <<-EOM
70
+
71
+ ========================================================================
72
+ ========================================================================
73
+
74
+ Performaning lint parsing
75
+
76
+ Enabled lint options:
77
+ #{enables.join("\n ")}
78
+
79
+ ************************************************************************
80
+
81
+ EOM
82
+
83
+ # configure the rake task to disable specific checks
84
+ if not disables.empty?
85
+ Rake::Task['lint'].clear
86
+ PuppetLint::RakeTask.new :lint do |config|
87
+ config.ignore_paths = ['spec/**/*.pp', 'vendor/**/*.pp']
88
+ config.log_format = '%{path}:%{linenumber}:%{check}:%{KIND}:%{message}'
89
+ config.fail_on_warnings = false
90
+ config.disable_checks = disables
91
+ end
92
+ end
93
+
94
+ begin
95
+ Rake.application['lint'].invoke
96
+ rescue SystemExit => e
97
+ puts <<-EOM
98
+
99
+ ************************************************************************
100
+
101
+ BUILD HAD FAILED
102
+
103
+ Correct the above Puppet LINT errors to correct
104
+
105
+ ************************************************************************
106
+
107
+ EOM
108
+ return false
109
+ end
110
+ return true
111
+ end
112
+
113
+
114
+ def process_rspec_tests(opts)
115
+
116
+ puts <<-EOM
117
+
118
+ ========================================================================
119
+ ========================================================================
120
+
121
+ Performaning RSpec unit testing
122
+
123
+ ************************************************************************
124
+
125
+ EOM
126
+
127
+ if opts.rspec_clean_sources
128
+ # execute rake spec_clean
129
+ puts "***"
130
+ puts "*** Cleaning spec fixtures"
131
+ puts "***"
132
+ Rake.application['spec_clean'].invoke
133
+ end
134
+
135
+ RSpec::Core::RakeTask.new(:spec) do |task|
136
+ task.rspec_opts = %w[--format RspecJunitFormatter --out test-reports/rspec.xml]
137
+ task.pattern = 'spec/{classes,defines,unit,functions,hosts,integration}/**/*_spec.rb'
138
+ end
139
+ Rake.application['spec'].invoke
140
+ end
141
+
142
+
143
+
144
+
145
+ if ENV['PUPPET_CI_CONF']
146
+ CONF_FILE = ENV['PUPPET_CI_CONF']
147
+ else
148
+ CONF_FILE = File.expand_path('../../etc/puppet_unittest_workflow.yaml', $0)
149
+ end
150
+
151
+ # Set script defaults
152
+ options = OpenStruct.new
153
+ options.syntax_run = true
154
+ options.syntax_checks = CheckFileSyntax::ALL_CHECKS
155
+ options.syntax_exclude_dirs = []
156
+ options.lint_run = true
157
+ options.lint_enable = []
158
+ options.rspec_run = true
159
+ options.rspec_clean_sources = false
160
+
161
+
162
+ # read in config file and set options
163
+ defaults = YAML.load_file(CONF_FILE)
164
+ defaults.keys.each do |test|
165
+ opts = defaults[test]
166
+
167
+ if test == 'syntax'
168
+ options.syntax_run = opts['run'] if opts.has_key? 'run'
169
+ options.syntax_checks = opts['checks'] if opts.has_key? 'checks'
170
+ options.syntax_exclude_dirs = opts['exclude_dirs'] if opts.has_key? 'exclude_dirs'
171
+ end
172
+
173
+ if test == 'lint'
174
+ options.lint_run = opts['run'] if opts.has_key? 'run'
175
+ options.lint_enable = opts['enable'] if opts.has_key? 'enable'
176
+ end
177
+
178
+ if test == 'rspec'
179
+ options.rspec_run = opts['run'] if opts.has_key? 'run'
180
+ options.rspec_clean_sources = opts['clean_sources'] if opts.has_key? 'clean_sources'
181
+ end
182
+
183
+ end
184
+
185
+
186
+ # process the command line options and override prev set settings
187
+ OptionParser.new do |opts|
188
+ opts.on('--[no-]lint', "Enable/disable lint parsing (Default: #{options[:lint]})") do |val|
189
+ options.lint_run = val
190
+ end
191
+
192
+ opts.on('--disable-syntax-check [TYPE]', 'Disable syntax check for TYPE') do |val|
193
+ if val.nil? or val =~ /all/i
194
+ options.syntax_run = false
195
+ else
196
+ options.syntax_checks.select! {|type| type != val.to_sym}
197
+ end
198
+ end
199
+
200
+ opts.on('--enable-syntax-check [TYPE]', 'Enable syntax checks for TYPE') do |val|
201
+ if val.nil?
202
+ options.syntax_checks = CheckFileSyntax::ALL_CHECKS
203
+ else
204
+ if not options.syntax_checks.include? val.to_sym
205
+ options.syntax_checks << val.to_sym
206
+ end
207
+ end
208
+ end
209
+
210
+ opts.on('--clean-sources', 'Clean out dependent sources and start from scratch') do
211
+ options.rspec_clean_sources = true
212
+ end
213
+
214
+
215
+ opts.on('--disable-rspec', 'Disable rspec unittests') do
216
+ options.rspec_run = false
217
+ end
218
+
219
+
220
+ opts.separator <<-EOH
221
+
222
+ Config file: #{CONF_FILE}
223
+ Config file location can be specified by setting $PUPPET_CI_CONF
224
+
225
+ Default syntax checks: #{options.syntax_checks.map {|i| i.to_s}.join ', '}
226
+
227
+ Using the keyword 'all' will allow all syntax checks to be enabled or
228
+ disabled. Order of enable/disable switches are important. Using a
229
+ disable switch at the end of options will turn off all syntax checks
230
+ even if there are enable syntax check switches on the command line.
231
+ EOH
232
+
233
+ end.parse!
234
+
235
+
236
+ if options.syntax_run
237
+ unless process_syntax_checks(options)
238
+ exit(1)
239
+ end
240
+ end
241
+
242
+
243
+ if options.lint_run
244
+ unless process_lint_parsing(options)
245
+ exit(2)
246
+ end
247
+ end
248
+
249
+
250
+ if options.rspec_run
251
+ process_rspec_tests(options)
252
+ end
253
+
@@ -0,0 +1,61 @@
1
+ ---
2
+ # Configuration for syntax checks
3
+ syntax:
4
+ run: true
5
+ # checks determines which syntax checkers to use
6
+ # checks:
7
+ # - ruby
8
+ # - erb
9
+ #
10
+ # exclude_dirs is a list of subdirectories to exclude from syntax checks
11
+ exclude_dirs:
12
+ - automation
13
+ - bin
14
+ - .git
15
+ - vendor
16
+ - spec
17
+ #
18
+ # Configuration for lint parsing
19
+ lint:
20
+ run: true
21
+ # enable turns on lint parsing options. They are puppet-lint options
22
+ # with '--no-' and '-check' removed from the option. Not specifying
23
+ # enable will cause all options to be turned on.
24
+ enable:
25
+ - right_to_left_relationship
26
+ # - autoloader_layout
27
+ - names_containing_dash
28
+ - class_inherits_from_params_class
29
+ - parameter_order
30
+ - inherits_across_namespaces
31
+ - nested_classes_or_defines
32
+ # - variable_scope
33
+ - slash_comments
34
+ - star_comments
35
+ - selector_inside_resource
36
+ - case_without_default
37
+ - documentation
38
+ # - double_quoted_strings
39
+ - only_variable_string
40
+ - variables_not_enclosed
41
+ - single_quote_string_with_variables
42
+ - quoted_booleans
43
+ - puppet_url_without_modules
44
+ - variable_contains_dash
45
+ - hard_tabs
46
+ - trailing_whitespace
47
+ # - 80chars
48
+ - 2sp_soft_tabs
49
+ - arrow_alignment
50
+ - unquoted_resource_title
51
+ - ensure_first_param
52
+ - duplicate_params
53
+ - unquoted_file_mode
54
+ - file_mode
55
+ - ensure_not_symlink_target
56
+ - unquoted_node_name
57
+ #
58
+ # Configuration for RSpec unit testing
59
+ rspec:
60
+ run: true
61
+ clean_sources: true
@@ -0,0 +1,184 @@
1
+ require 'colorize'
2
+ require 'json'
3
+ require 'yaml'
4
+ require 'find'
5
+
6
+
7
+ module CheckFileSyntax
8
+
9
+ ALL_CHECKS = [:puppet, :ruby, :python, :perl, :bash, :erb, :yaml, :json]
10
+
11
+ module_function
12
+ def type_of_file(path, interpreter, extensions)
13
+ # check extensions first
14
+ [extensions].flatten.each {|ext| return true if path.end_with? ext }
15
+
16
+ # check only if really a file and is not 0 byte
17
+ if File.file?(path) and File.size?(path)
18
+ # Look for a she-bang line and check for interpreter
19
+ shebang = File.open(path).first
20
+ if shebang and shebang.start_with? '#!/' and shebang.include? interpreter.to_s
21
+ return true
22
+ end
23
+ end
24
+ return false
25
+ end
26
+
27
+ # define a bunch of convenience functions
28
+ def puppet_file?(path)
29
+ type_of_file(path, :puppet, '.pp')
30
+ end
31
+
32
+ def erb_file?(path)
33
+ type_of_file(path, :erb, '.erb')
34
+ end
35
+
36
+ def python_file?(path)
37
+ type_of_file(path, :python, '.py')
38
+ end
39
+
40
+ def ruby_file?(path)
41
+ type_of_file(path, :ruby, '.rb')
42
+ end
43
+
44
+ def perl_file?(path)
45
+ type_of_file(path, :perl, ['.pl', '.pm'])
46
+ end
47
+
48
+ def bash_file?(path)
49
+ type_of_file(path, :bash, ['.sh', '.bash', '.zsh', '.ksh'])
50
+ end
51
+
52
+ def json_file?(path)
53
+ type_of_file(path, :json, '.json')
54
+ end
55
+
56
+ def yaml_file?(path)
57
+ type_of_file(path, '---', ['.yaml', '.yml'])
58
+ end
59
+
60
+
61
+ module_function
62
+ def show_status (name, success, errors)
63
+ # Untested files return a nil success
64
+ unless success.nil?
65
+ if success == :passed
66
+ puts ' OK '.colorize(:green) + " #{name}".colorize(:cyan)
67
+ else
68
+ puts ' FAIL '.colorize(:light_yellow).swap + " #{name}".colorize(:cyan)
69
+ puts errors
70
+ end
71
+ end
72
+ end
73
+
74
+
75
+ module_function
76
+ def search_all_files_for_errors(directory, excludes=[], checks=ALL_CHECKS, &block)
77
+ error_count = 0
78
+ Find.find(directory) do |path|
79
+ # prune the directory tree if we found a directory that should be excluded
80
+ if File.directory? path
81
+ if not (excludes.select { |d| path.end_with? d }).empty?
82
+ Find.prune
83
+ else
84
+ # we don't do any thing with dirs, so go to next item
85
+ next
86
+ end
87
+ end
88
+
89
+ # TODO Need to look at checks to determine if we should do this
90
+ check_file_syntax(path) do |path, status, errors|
91
+ if status == :failed
92
+ error_count += 1
93
+ end
94
+
95
+ if block_given?
96
+ yield path, status, errors
97
+ else
98
+ show_status(path, status, errors)
99
+ end
100
+ end
101
+ end
102
+ return error_count
103
+ end
104
+
105
+
106
+ module_function
107
+ def check_file_syntax(path, &block)
108
+ errors = ''
109
+ status = nil
110
+
111
+ if puppet_file? path
112
+ if system('which puppet >/dev/null')
113
+ errors = `puppet parser validate #{path} 2>&1`
114
+ status = $?.success? ? :passed : :failed
115
+ else
116
+ puts 'Consider installing puppet so that syntax can be checked.'.colorize(:yellow)
117
+ status = :skipped
118
+ end
119
+ end
120
+
121
+ if erb_file? path
122
+ errors = `cat #{path} | erb -x -T - | ruby -c 2>&1`
123
+ status = $?.success? ? :passed : :failed
124
+ end
125
+
126
+ if python_file? path
127
+ if system('which python >/dev/null')
128
+ errors = `python -m py_compile #{path} 2>&1`
129
+ status = $?.success? ? :passed : :failed
130
+ else
131
+ puts 'Consider installing python so that syntax can be checked.'.colorize(:yellow)
132
+ status = :skipped
133
+ end
134
+ end
135
+
136
+ if ruby_file? path
137
+ errors = `ruby -c #{path} 2>&1`
138
+ status = $?.success? ? :passed : :failed
139
+ end
140
+
141
+ if perl_file? path
142
+ if system('which perl >/dev/null')
143
+ errors = `perl -c #{path} 2>&1`
144
+ status = $?.success? ? :passed : :failed
145
+ else
146
+ puts 'Consider installing perl so that syntax can be checked.'.colorize(:yellow)
147
+ status = :skipped
148
+ end
149
+ end
150
+
151
+ if bash_file? path
152
+ errors = `bash -n #{path} 2>&1`.to_i
153
+ status = $?.success? ? :passed : :failed
154
+ end
155
+
156
+
157
+ if json_file? path
158
+ begin
159
+ JSON.parse(File.read(path))
160
+ status = :passed
161
+ rescue Exception => e
162
+ errors = e.message
163
+ status = :failed
164
+ end
165
+ end
166
+
167
+ if yaml_file? path
168
+ begin
169
+ YAML.parse(File.read(path))
170
+ status = :passed
171
+ rescue Exception => e
172
+ errors = e.message
173
+ status = :failed
174
+ end
175
+ end
176
+
177
+ if block_given?
178
+ yield path, status, errors
179
+ else
180
+ show_status(path, status, errors)
181
+ error_count += 1 if status == :failed
182
+ end
183
+ end
184
+ end