Class: ArduinoCI::CIConfig

Inherits:
Object
  • Object
show all
Defined in:
lib/arduino_ci/ci_config.rb

Overview

Provide the configuration and CI plan

  • Read from a base config with default platforms defined

  • Allow project-specific overrides of platforms

  • Allow example-specific allowance of platforms to test

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeCIConfig

Returns a new instance of CIConfig.



73
74
75
76
77
78
79
# File 'lib/arduino_ci/ci_config.rb', line 73

def initialize
  @is_default    = false
  @package_info  = {}
  @platform_info = {}
  @compile_info  = {}
  @unittest_info = {}
end

Instance Attribute Details

#compile_infoObject

Returns the value of attribute compile_info.



70
71
72
# File 'lib/arduino_ci/ci_config.rb', line 70

def compile_info
  @compile_info
end

#is_defaultObject (readonly)

Returns the value of attribute is_default.



67
68
69
# File 'lib/arduino_ci/ci_config.rb', line 67

def is_default
  @is_default
end

#package_infoObject

Returns the value of attribute package_info.



68
69
70
# File 'lib/arduino_ci/ci_config.rb', line 68

def package_info
  @package_info
end

#platform_infoObject

Returns the value of attribute platform_info.



69
70
71
# File 'lib/arduino_ci/ci_config.rb', line 69

def platform_info
  @platform_info
end

#unittest_infoObject

Returns the value of attribute unittest_info.



71
72
73
# File 'lib/arduino_ci/ci_config.rb', line 71

def unittest_info
  @unittest_info
end

Class Method Details

.defaultArudinoCI::CIConfig

load the default set of platforms

Returns:

  • (ArudinoCI::CIConfig)

    The configuration with defaults filled in



59
60
61
62
63
64
# File 'lib/arduino_ci/ci_config.rb', line 59

def default
  ret = new
  ret.instance_variable_set("@is_default", true)
  ret.load_yaml((Pathname.new(__dir__) + "../../misc/default.yml").realpath)
  ret
end

Instance Method Details

#allowable_unittest_files(paths) ⇒ Array<Pathname>

Config allows select / reject (aka whitelist / blacklist) criteria. Enforce on a dir

Parameters:

  • paths (Array<Pathname>)

    the initial set of test files

Returns:

  • (Array<Pathname>)

    files that match the select/reject criteria



309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
# File 'lib/arduino_ci/ci_config.rb', line 309

def allowable_unittest_files(paths)
  return paths if @unittest_info[:testfiles].nil?

  ret = paths
  # Check for array emptiness, otherwise nothing will be selected!
  unless @unittest_info[:testfiles][:select].nil? || @unittest_info[:testfiles][:select].empty?
    ret.select! { |p| unittest_info[:testfiles][:select].any? { |glob| p.basename.fnmatch(glob) } }
  end

  # It's OK for the :reject array to be empty, that means nothing will be rejected by default
  unless @unittest_info[:testfiles][:reject].nil?
    ret.reject! { |p| unittest_info[:testfiles][:reject].any? { |glob| p.basename.fnmatch(glob) } }
  end
  ret
end

#apply_configuration(yml) ⇒ ArduinoCI::CIConfig

Load configuration from a hash

Parameters:

  • yml (Hash)

    the source data

Returns:



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/arduino_ci/ci_config.rb', line 142

def apply_configuration(yml)
  if yml.include?("packages")
    yml["packages"].each do |k, v|
      valid_data = validate_data("packages", v, PACKAGE_SCHEMA)
      @package_info[k] = valid_data
    end
  end

  if yml.include?("platforms")
    yml["platforms"].each do |k, v|
      valid_data = validate_data("platforms", v, PLATFORM_SCHEMA)
      @platform_info[k] = valid_data
    end
  end

  if yml.include?("compile")
    valid_data = validate_data("compile", yml["compile"], COMPILE_SCHEMA)
    valid_data.each { |k, v| @compile_info[k] = v }
  end

  if yml.include?("unittest")
    valid_data = validate_data("unittest", yml["unittest"], UNITTEST_SCHEMA)
    valid_data.each { |k, v| @unittest_info[k] = v }
  end

  self
end

#aux_libraries_for_buildArray<String>

Returns The aux libraries required for building/verifying.

Returns:

  • (Array<String>)

    The aux libraries required for building/verifying



293
294
295
296
297
# File 'lib/arduino_ci/ci_config.rb', line 293

def aux_libraries_for_build
  return [] if @compile_info[:libraries].nil?

  @compile_info[:libraries]
end

#aux_libraries_for_unittestArray<String>

Returns The aux libraries required for unit testing.

Returns:

  • (Array<String>)

    The aux libraries required for unit testing



300
301
302
303
304
# File 'lib/arduino_ci/ci_config.rb', line 300

def aux_libraries_for_unittest
  return [] if @unittest_info[:libraries].nil?

  @unittest_info[:libraries]
end

#available_override_config_path(base_dir = nil) ⇒ Pathname

Get available configuration file, if one exists

Parameters:

  • base_dir (String) (defaults to: nil)

    The directory in which to search for a config file

Returns:

  • (Pathname)

    the first available config file we could find, or nil



202
203
204
# File 'lib/arduino_ci/ci_config.rb', line 202

def available_override_config_path(base_dir = nil)
  CONFIG_FILENAMES.map { |f| base_dir.nil? ? Pathname.new(f) : base_dir + f }.find(&:exist?)
end

#cloneArduinoCI::CIConfig

Create a clone of this configuration and return it

Returns:



172
173
174
175
176
177
178
179
# File 'lib/arduino_ci/ci_config.rb', line 172

def clone
  cloned_config = self.class.new
  cloned_config.package_info  = deep_clone(@package_info)
  cloned_config.platform_info = deep_clone(@platform_info)
  cloned_config.compile_info  = deep_clone(@compile_info)
  cloned_config.unittest_info = deep_clone(@unittest_info)
  cloned_config
end

#compilers_to_useArray<String>

compilers to build (unit tests) with

Returns:

  • (Array<String>)

    The compiler binary names (e.g. g++) to build with



262
263
264
265
266
# File 'lib/arduino_ci/ci_config.rb', line 262

def compilers_to_use
  return [] if @unittest_info[:compilers].nil?

  @unittest_info[:compilers]
end

#deep_clone(hash) ⇒ Hash

Deep-clone a hash

Parameters:

  • hash (Hash)

    the source data

Returns:

  • (Hash)

    a copy



99
100
101
# File 'lib/arduino_ci/ci_config.rb', line 99

def deep_clone(hash)
  Marshal.load(Marshal.dump(hash))
end

#exclude_dirsArray<String>

paths to exclude all files in for building and unitttests

Returns:

  • (Array<String>)

    The directories (relative to base dir) to exclude



270
271
272
273
274
# File 'lib/arduino_ci/ci_config.rb', line 270

def exclude_dirs
  return [] if @unittest_info[:exclude_dirs].nil?

  @unittest_info[:exclude_dirs]
end

#from_example(example_path) ⇒ ArduinoCI::CIConfig

Produce a configuration override taken from an Arduino library example path handle either path to example file or example dir

Parameters:

  • path (Pathname)

    the path to the settings yaml file

Returns:



235
236
237
238
# File 'lib/arduino_ci/ci_config.rb', line 235

def from_example(example_path)
  ovr = override_file_from_example(example_path)
  ovr.nil? ? self : with_override(ovr)
end

#from_project_libraryArduinoCI::CIConfig

Produce a configuration, assuming the CI script runs from the working directory of the base project

Returns:



226
227
228
229
# File 'lib/arduino_ci/ci_config.rb', line 226

def from_project_library
  ovr = override_file_from_project_library
  ovr.nil? ? self : with_override(ovr)
end

#gcc_config(platform_name) ⇒ Hash

get GCC configuration for a given platform

Parameters:

  • platform_name (String)

    The name of the platform as defined in yaml

Returns:

  • (Hash)

    the settings



328
329
330
331
332
333
334
# File 'lib/arduino_ci/ci_config.rb', line 328

def gcc_config(platform_name)
  plat = @platform_info[platform_name]
  return {} if plat.nil?
  return {} if plat[:gcc].nil?

  plat[:gcc]
end

#load_yaml(path) ⇒ ArduinoCI::CIConfig

Load configuration yaml from a file

Parameters:

  • path (String)

    the source file

Returns:

Raises:



132
133
134
135
136
137
# File 'lib/arduino_ci/ci_config.rb', line 132

def load_yaml(path)
  yml = YAML.load_file(path)
  raise ConfigurationError, "The YAML file at #{path} failed to load" unless yml

  apply_configuration(yml)
end

#override_file_from_example(example_path) ⇒ Pathname

Find an available override file from an example sketch

Parameters:

  • path (Pathname)

    the path to the example or example directory

Returns:

  • (Pathname)

    A file that can override project config, or nil if none was found



219
220
221
222
# File 'lib/arduino_ci/ci_config.rb', line 219

def override_file_from_example(example_path)
  base_dir = example_path.directory? ? example_path : example_path.dirname
  available_override_config_path(base_dir)
end

#override_file_from_project_libraryPathname

TODO:

this is currently reliant on launching the arduino_ci.rb test runner from the correct working directory

Find an available override file from the project directory

Returns:

  • (Pathname)

    A file that can override project config, or nil if none was found



211
212
213
# File 'lib/arduino_ci/ci_config.rb', line 211

def override_file_from_project_library
  available_override_config_path(nil)
end

#package_url(package) ⇒ String

the URL that gives the download info for a given package (a JSON file). this is NOT where the package comes from.

Parameters:

  • package (String)

    the package name (e.g. “arduino:avr”)

Returns:

  • (String)

    the URL defined for this package



254
255
256
257
258
# File 'lib/arduino_ci/ci_config.rb', line 254

def package_url(package)
  return nil if @package_info[package].nil?

  @package_info[package][:url]
end

#platform_definition(platform_name) ⇒ Hash

get information about a given platform: board name, package name, compiler stuff, etc

Parameters:

  • platform_name (String)

    The name of the platform as defined in yaml

Returns:

  • (Hash)

    the settings object



243
244
245
246
247
248
# File 'lib/arduino_ci/ci_config.rb', line 243

def platform_definition(platform_name)
  defn = @platform_info[platform_name]
  return nil if defn.nil?

  deep_clone(defn)
end

#platforms_to_buildArray<String>

platforms to build [the examples on]

Returns:

  • (Array<String>)

    The platforms to build



278
279
280
281
282
# File 'lib/arduino_ci/ci_config.rb', line 278

def platforms_to_build
  return [] if @compile_info[:platforms].nil?

  @compile_info[:platforms]
end

#platforms_to_unittestArray<String>

platforms to unit test [the tests on]

Returns:

  • (Array<String>)

    The platforms to unit test on



286
287
288
289
290
# File 'lib/arduino_ci/ci_config.rb', line 286

def platforms_to_unittest
  return [] if @unittest_info[:platforms].nil?

  @unittest_info[:platforms]
end

#to_hHash

Returns config data as a hash.

Returns:

  • (Hash)

    config data as a hash



82
83
84
85
86
87
88
89
# File 'lib/arduino_ci/ci_config.rb', line 82

def to_h
  {
    packages: @package_info,
    platforms: @platform_info,
    compile: @compile_info,
    unittest: @unittest_info
  }
end

#to_sString

Returns config data as a string.

Returns:

  • (String)

    config data as a string



92
93
94
# File 'lib/arduino_ci/ci_config.rb', line 92

def to_s
  to_h.to_s
end

#validate_data(rootname, source, schema) ⇒ Hash

validate a data source according to a schema print out warnings for bad fields, and return only the good ones

Parameters:

  • rootname (String)

    the name, for printing

  • source (Hash)

    source data

  • schema (Hash)

    a mapping of field names to their expected type

Returns:

  • (Hash)

    a copy, containing only expected & valid data



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/arduino_ci/ci_config.rb', line 109

def validate_data(rootname, source, schema)
  return nil if source.nil?

  good_data = {}
  source.each do |key, value|
    ksym = key.to_sym
    expected_type = schema[ksym].instance_of?(Class) ? schema[ksym] : Hash
    if !schema.include?(ksym)
      puts "Warning: unknown field '#{ksym}' under definition for #{rootname}"
    elsif value.nil?
      good_data[ksym] = nil
    elsif value.class != expected_type
      puts "Warning: expected field '#{ksym}' of #{rootname} to be '#{expected_type}', got '#{value.class}'"
    else
      good_data[ksym] = value.instance_of?(Hash) ? validate_data(key, value, schema[ksym]) : value
    end
  end
  good_data
end

#with_override(path) ⇒ ArduinoCI::CIConfig

Override these settings with settings from another file

Parameters:

  • path (String)

    the path to the settings yaml file

Returns:



184
185
186
187
188
# File 'lib/arduino_ci/ci_config.rb', line 184

def with_override(path)
  overridden_config = clone
  overridden_config.load_yaml(path)
  overridden_config
end

#with_override_config(config_hash) ⇒ ArduinoCI::CIConfig

Override these settings with settings from a hash

Parameters:

  • config_hash (Hash)

    A configuration hash

Returns:



193
194
195
196
197
# File 'lib/arduino_ci/ci_config.rb', line 193

def with_override_config(config_hash)
  overridden_config = clone
  overridden_config.apply_configuration(config_hash)
  overridden_config
end