Module: Configuration
- Included in:
- PotentialBuild
- Defined in:
- lib/configuration.rb
Overview
tools for loading and parsing of yaml config files and filling in the details. A minimal merged config should at least define the compiler. Individual setup* functions in this module will raise Exceptions for invalid conditions, while blanks will be applied if it is a suitable default.
Instance Method Summary collapse
- #_setup_cc_and_cxx(compiler, cc_name, cxx_name) ⇒ Object
- #establish_base_configuration(os_version, os_release) ⇒ Object
-
#establish_os_characteristics ⇒ Object
:nocov:.
-
#establish_windows_characteristics ⇒ Object
:nocov: Not doing any testing on Windows right now.
-
#find_valid_yaml_files(all_yaml_names, location, ref, fileset) ⇒ Object
returns a list of yaml-based configuration data sets they may be nil values if the yaml config couldn't be found by name.
- #get_all_yaml_names(os_version, os_release, os_distribution) ⇒ Object
- #load_configuration(location, ref, is_release) ⇒ Object
- #load_yaml(name, this_location, this_ref) ⇒ Object
- #setup_compiler_architecture(compiler) ⇒ Object
- #setup_compiler_build_generator(compiler) ⇒ Object
- #setup_compiler_description(compiler) ⇒ Object
- #setup_compiler_extra_flags(compiler, is_release) ⇒ Object
- #setup_compiler_num_processors(compiler) ⇒ Object
- #setup_compiler_target_arch(compiler) ⇒ Object
- #setup_compiler_version(compiler) ⇒ Object
- #setup_gcc_style_cc_and_cxx(compiler) ⇒ Object
- #setup_single_compiler(compiler, is_release) ⇒ Object
- #symbolize(obj) ⇒ Object
- #which(cmd, extra_paths = nil) ⇒ Object
Instance Method Details
#_setup_cc_and_cxx(compiler, cc_name, cxx_name) ⇒ Object
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 |
# File 'lib/configuration.rb', line 219 def _setup_cc_and_cxx(compiler, cc_name, cxx_name) potential_name = which("#{cc_name}-#{compiler[:version]}") if potential_name.nil? cc_bin = which(cc_name) cxx_bin = which(cxx_name) else cc_bin = potential_name cxx_bin = which("#{cxx_name}-#{compiler[:version]}") end if cc_bin.nil? || cxx_bin.nil? || (`#{cc_bin} --version` !~ /.*#{compiler[:version]}/) || (`#{cxx_bin} --version` !~ /.*#{compiler[:version]}/) raise CannotMatchCompiler, "Unable to find appropriate compiler for: #{compiler[:name]} version #{compiler[:version]}" end [cc_bin, cxx_bin] end |
#establish_base_configuration(os_version, os_release) ⇒ Object
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/configuration.rb', line 116 def establish_base_configuration(os_version, os_release) cmake_paths = ['C:\\Program Files\\CMake\\bin', 'C:\\Program Files (x86)\\CMake\\bin', 'C:\\Program Files\\CMake 3.0\\bin', 'C:\\Program Files (x86)\\CMake 3.0\\bin', 'C:\\Program Files\\CMake 2.8\\bin', 'C:\\Program Files (x86)\\CMake 2.8\\bin', 'C:\\ProgramData\\chocolatey\\bin'] { :os => os_version, :os_release => os_release, :engine => 'cmake', :post_results_comment => true, :post_results_status => true, :cmake_bin => "\"#{which('cmake', cmake_paths)}\"", :ctest_bin => "\"#{which('ctest', cmake_paths)}\"" } end |
#establish_os_characteristics ⇒ Object
:nocov:
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/configuration.rb', line 81 def establish_os_characteristics # if RUBY_VERSION[0..2].to_f < 2.4 # we must not use match?, it isn't available... # for now I'll just try to use without ? everywhere, we'll see # end case RUBY_PLATFORM when /darwin/i os_distribution = nil os_version = 'MacOS' ver_string = `uname -v`.strip /.* Version (?<ver_major>[0-9]+)\.([0-9]+)\.([0-9]+).*:.*/ =~ ver_string # the darwin version number - 4 = the point release of macosx os_release = "10.#{ver_major.to_i - 4}" when /linux/i os_distribution = `lsb_release -is`.strip os_version = 'Linux' os_release = "#{`lsb_release -is`.strip}-#{`lsb_release -rs`.strip}" else # :nocov: Not testing on windows right now os_distribution, os_version, os_release = establish_windows_characteristics # :nocov: end [os_distribution, os_version, os_release] end |
#establish_windows_characteristics ⇒ Object
:nocov: Not doing any testing on Windows right now
70 71 72 73 74 75 76 77 78 |
# File 'lib/configuration.rb', line 70 def establish_windows_characteristics os_version = 'Windows' ver_string = `cmd /c ver`.strip /.* \[Version (?<ver_major>[0-9]+)\.(?<ver_minor>[0-9]+)\..*\]/ =~ ver_string os_release = nil os_release = '10' if ver_major.to_i == 10 os_release = "Unknown-#{ver_major}.#{ver_minor}" if os_release.nil? [nil, os_version, os_release] end |
#find_valid_yaml_files(all_yaml_names, location, ref, fileset) ⇒ Object
returns a list of yaml-based configuration data sets they may be nil values if the yaml config couldn't be found by name
138 139 140 141 142 143 144 145 |
# File 'lib/configuration.rb', line 138 def find_valid_yaml_files(all_yaml_names, location, ref, fileset) valid_yaml_configs = [] all_yaml_names.each do |yaml| attempted_yaml = load_yaml(yaml, location, ref) valid_yaml_configs << attempted_yaml if fileset.include?(yaml) end valid_yaml_configs end |
#get_all_yaml_names(os_version, os_release, os_distribution) ⇒ Object
106 107 108 109 110 111 112 113 114 |
# File 'lib/configuration.rb', line 106 def get_all_yaml_names(os_version, os_release, os_distribution) yaml_base_name = '.decent_ci' yaml_name = "#{yaml_base_name}.yaml" yaml_os_name = "#{yaml_base_name}-#{os_version}.yaml" yaml_os_release_name = "#{yaml_base_name}-#{os_version}-#{os_release}.yaml" yaml_os_distribution_name = nil yaml_os_distribution_name = "#{yaml_base_name}-#{os_version}-#{os_distribution}.yaml" unless os_distribution.nil? [yaml_name, yaml_os_name, yaml_os_release_name, yaml_os_distribution_name] end |
#load_configuration(location, ref, is_release) ⇒ Object
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 |
# File 'lib/configuration.rb', line 276 def load_configuration(location, ref, is_release) # first get a list of all decent_ci files found at the root of the repo, and raise if none were found fileset = Set.new @client.content(location, :path => '.', :ref => ref).each do |path| fileset << path.name if path.name =~ /\.decent_ci.*/ end $logger.debug("For ref #{ref} .decent_ci files located: #{fileset.to_a}") raise NoDecentCIFiles, 'No .decent_ci input files' if fileset.empty? # then try to form up a final merged configuration of all the yaml files found and symbolize it, raise if no compilers found os_distribution, os_version, os_release = establish_os_characteristics yaml_names = get_all_yaml_names(os_version, os_release, os_distribution) valid_yamls = find_valid_yaml_files(yaml_names, location, ref, fileset) result_yaml = establish_base_configuration(os_version, os_release) valid_yamls.each do |yaml| result_yaml.merge!(yaml) unless yaml.nil? end result_yaml = symbolize(result_yaml) $logger.debug("Final merged configuration: #{result_yaml}") # create a configuration struct from the yaml data and escape early if there aren't any compilers configuration = OpenStruct.new(result_yaml) raise 'No compilers defined' if configuration.compilers.nil? # loop over all compilers and fill in defaults and check for erroneous conditions configuration.compilers.each do |compiler| $logger.debug("Working on compiler: #{compiler[:name]}") setup_single_compiler(compiler, is_release) end # do final touchups on the configuration configuration.aging_pull_requests_notification = true if configuration.aging_pull_requests_notification.nil? configuration.aging_pull_requests_numdays = 7 if configuration.aging_pull_requests_numdays.nil? configuration.test_pass_limit = 99.9999 if configuration.test_pass_limit.nil? configuration.test_warn_limit = 90.00 if configuration.test_warn_limit.nil? configuration end |
#load_yaml(name, this_location, this_ref) ⇒ Object
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/configuration.rb', line 30 def load_yaml(name, this_location, this_ref) return nil if this_location.nil? || name.nil? begin content = @client.content(this_location, :path => name, :ref => this_ref) contents = content.content return_value = YAML.load(Base64.decode64(contents.to_s)) rescue Psych::SyntaxError, SyntaxError => e raise "#{e.} while parsing #{name}@#{this_ref}" rescue => e $logger.debug("Unable to load yaml file from repository: #{this_location}/#{name}@#{this_ref} error: #{e}") path = File.(name, this_location) $logger.debug("Attempting to load yaml config file: #{path}") if File.exist?(path) return_value = YAML.load_file(path) else $logger.debug("yaml file does not exist: #{path}") return_value = nil end end return_value end |
#setup_compiler_architecture(compiler) ⇒ Object
147 148 149 150 151 152 153 154 155 |
# File 'lib/configuration.rb', line 147 def setup_compiler_architecture(compiler) return compiler[:architecture] unless compiler[:architecture].nil? if compiler[:name] == 'Visual Studio' 'i386' else RbConfig::CONFIG['host_cpu'] end end |
#setup_compiler_build_generator(compiler) ⇒ Object
199 200 201 202 203 204 205 206 207 |
# File 'lib/configuration.rb', line 199 def setup_compiler_build_generator(compiler) return compiler[:build_generator] unless compiler[:build_generator].nil? if compiler[:name].match(/.*Visual Studio.*/i) 'Visual Studio 16 2019' else 'Unix Makefiles' end end |
#setup_compiler_description(compiler) ⇒ Object
173 174 175 176 177 178 179 |
# File 'lib/configuration.rb', line 173 def setup_compiler_description(compiler) raise 'Compiler name not specified, must at least specify name' if compiler[:name].nil? description = compiler[:name].gsub(/\s+/, '') description = "#{description}-#{compiler[:version]}" unless compiler[:version].nil? description end |
#setup_compiler_extra_flags(compiler, is_release) ⇒ Object
181 182 183 184 185 186 187 188 189 |
# File 'lib/configuration.rb', line 181 def setup_compiler_extra_flags(compiler, is_release) if is_release && !compiler[:cmake_extra_flags_release].nil? compiler[:cmake_extra_flags_release] elsif compiler[:cmake_extra_flags].nil? '' else compiler[:cmake_extra_flags] end end |
#setup_compiler_num_processors(compiler) ⇒ Object
191 192 193 194 195 196 197 |
# File 'lib/configuration.rb', line 191 def setup_compiler_num_processors(compiler) return compiler[:num_parallel_builds] unless compiler[:num_parallel_builds].nil? num_processors = processor_count num_processors -= 1 if num_processors > 2 num_processors end |
#setup_compiler_target_arch(compiler) ⇒ Object
209 210 211 212 213 214 215 216 217 |
# File 'lib/configuration.rb', line 209 def setup_compiler_target_arch(compiler) if compiler[:name].match(/.*Visual Studio.*/i) # Visual Studio 2019+ generator behaves slightly different, need to add -A return 'x64' if !compiler[:architecture].nil? && compiler[:architecture].match(/.*64.*/) return 'Win32' end compiler[:architecture] end |
#setup_compiler_version(compiler) ⇒ Object
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/configuration.rb', line 157 def setup_compiler_version(compiler) return compiler[:version] unless compiler[:version].nil? case compiler[:name] when 'Visual Studio' raise 'Version number for visual studio must be provided' when 'clang' /.*clang version (?<version>([0-9]+\.?)+).*/ =~ `clang --version` version when 'gcc' `gcc -dumpversion` else raise 'Invalid compiler specified, must be one of clang, gcc, or a variation on "Visual Studio VV YYYY"' end end |
#setup_gcc_style_cc_and_cxx(compiler) ⇒ Object
236 237 238 239 240 241 242 243 244 245 246 247 248 |
# File 'lib/configuration.rb', line 236 def setup_gcc_style_cc_and_cxx(compiler) return [compiler[:cc_bin], compiler[:cxx_bin]] unless compiler[:cc_bin].nil? || compiler[:cxx_bin].nil? return [nil, nil] if compiler[:name].nil? || !%w[clang gcc].include?(compiler[:name]) if compiler[:name] == 'clang' cc_bin, cxx_bin = _setup_cc_and_cxx(compiler, 'clang', 'clang++') else # gcc cc_bin, cxx_bin = _setup_cc_and_cxx(compiler, 'gcc', 'g++') end [cc_bin, cxx_bin] end |
#setup_single_compiler(compiler, is_release) ⇒ Object
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 |
# File 'lib/configuration.rb', line 250 def setup_single_compiler(compiler, is_release) compiler[:architecture] = setup_compiler_architecture(compiler) compiler[:version] = setup_compiler_version(compiler) compiler[:cc_bin], compiler[:cxx_bin] = setup_gcc_style_cc_and_cxx(compiler) compiler[:analyze_only] = false compiler[:release_only] = false if compiler[:release_only].nil? compiler[:skip_packaging] = (compiler[:skip_packaging] =~ /true/i) || compiler[:skip_packaging] if compiler[:skip_packaging].nil? compiler[:description] = setup_compiler_description(compiler) compiler[:build_type] = 'Release' if compiler[:build_type].nil? || compiler[:build_type] == '' compiler[:build_generator] = setup_compiler_build_generator(compiler) compiler[:target_arch] = setup_compiler_target_arch(compiler) compiler[:skip_regression] = false if compiler[:skip_regression].nil? compiler[:collect_performance_results] = false if compiler[:collect_performance_results].nil? compiler[:ctest_filter] = '' if compiler[:ctest_filter].nil? compiler[:coverage_base_dir] = '' if compiler[:coverage_base_dir].nil? compiler[:coverage_enabled] = false if compiler[:coverage_enabled].nil? compiler[:coverage_pass_limit] = 90 if compiler[:coverage_pass_limit].nil? compiler[:coverage_warn_limit] = 75 if compiler[:coverage_warn_limit].nil? compiler[:cmake_extra_flags] = setup_compiler_extra_flags(compiler, is_release) compiler[:num_parallel_builds] = setup_compiler_num_processors(compiler) raise CannotMatchCompiler, 'Decent CI currently only deployed with Visual Studio version 16 (2019)' if compiler[:name] =~ /.*Visual Studio.*/i && compiler[:version] != 16 compiler end |
#symbolize(obj) ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/configuration.rb', line 53 def symbolize(obj) case obj when Hash obj.reduce({}) do |memo, (k, v)| memo.tap { |m| m[k.to_sym] = symbolize(v) } end when Array obj.reduce([]) do |memo, v| memo << symbolize(v) memo end else obj end end |
#which(cmd, extra_paths = nil) ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/configuration.rb', line 16 def which(cmd, extra_paths = nil) exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : [''] path_array = ENV['PATH'].split(File::PATH_SEPARATOR) path_array.concat(extra_paths) unless extra_paths.nil? path_array.each do |path| exts.each do |ext| exe = File.join(path, "#{cmd}#{ext}") return Pathname.new(exe).cleanpath.to_s if File.executable? exe end end nil end |