Skip to content

Commit

Permalink
Enable custom installation scripts during CI
Browse files Browse the repository at this point in the history
  • Loading branch information
ianfixes committed Dec 28, 2020
1 parent 6aef89f commit c6f4d73
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 4 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Added
- Environment variable to run a custom initialization script during CI testing: `CUSTOM_INIT_SCRIPT`

### Changed

Expand All @@ -22,7 +23,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [1.1.0] - 2020-12-02
### Added
- `ensure_arduino_installation.rb` now ensures the existence of the library directory as well
- Environment variables to escalate unit tests or examples not being found during CI testing
- Environment variables to escalate unit tests or examples not being found during CI testing - `EXPECT_EXAMPLES` and `EXPECT_UNITTESTS`

### Changed
- Conserve CI testing minutes by grouping CI into fewer runs
Expand Down
5 changes: 5 additions & 0 deletions REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ This allows a file (or glob) pattern to be executed in your tests directory, cre
This allows a file (or glob) pattern to be executed in your tests directory, creating a blacklist of files to skip. E.g. `--testfile-reject=test_animal_*.cpp` would match `test_animal_cat.cpp` and `test_animal_dog.cpp` (skipping those) and test only `test_plant_rose.cpp`, `test_plant_daisy.cpp`, etc.


### `CUSTOM_INIT_SCRIPT` environment variable

If set, testing will execute (using `/bin/sh`) the script referred to by this variable -- relative to the current working directory. This enables use cases like the GitHub action to install custom library versions (i.e. a version of a library that is different than what the library manager would automatically install by name) prior to CI test runs.


### `EXPECT_UNITTESTS` environment variable

If set, testing will fail if no unit test files are detected (or if the directory does not exist). This is to avoid communicating a passing status in cases where a commit may have accidentally moved or deleted the test files.
Expand Down
36 changes: 33 additions & 3 deletions exe/arduino_ci.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
require 'optparse'

WIDTH = 80
VAR_EXPECT_EXAMPLES = "EXPECT_EXAMPLES".freeze
VAR_EXPECT_UNITTESTS = "EXPECT_UNITTESTS".freeze
VAR_CUSTOM_INIT_SCRIPT = "CUSTOM_INIT_SCRIPT".freeze
VAR_EXPECT_EXAMPLES = "EXPECT_EXAMPLES".freeze
VAR_EXPECT_UNITTESTS = "EXPECT_UNITTESTS".freeze

@failure_count = 0
@passfail = proc { |result| result ? "✓" : "✗" }
Expand Down Expand Up @@ -51,6 +52,8 @@ def self.parse(options)
puts opts
puts
puts "Additionally, the following environment variables control the script:"
puts " - #{VAR_CUSTOM_INIT_SCRIPT} - if set, this script will be run from the Arduino/libraries directory"
puts " prior to any automated library installation or testing (e.g. to install unoffical libraries)"
puts " - #{VAR_EXPECT_EXAMPLES} - if set, testing will fail if no example sketches are present"
puts " - #{VAR_EXPECT_UNITTESTS} - if set, testing will fail if no unit tests are present"
exit
Expand All @@ -68,7 +71,7 @@ def self.parse(options)
# terminate after printing any debug info. TODO: capture debug info
def terminate(final = nil)
puts "Failures: #{@failure_count}"
unless @failure_count.zero? || final
unless @failure_count.zero? || final || @backend.nil?
puts "Last message: #{@backend.last_msg}"
puts "========== Stdout:"
puts @backend.last_out
Expand Down Expand Up @@ -277,6 +280,30 @@ def get_annotated_compilers(config, cpp_library)
compilers
end

# Handle existence or nonexistence of custom initialization script -- run it if you have it
#
# This feature is to drive GitHub actions / docker image installation where the container is
# in a clean-slate state but needs some way to have custom library versions injected into it.
# In this case, the user provided script would fetch a git repo or some other method
def perform_custom_initialization(_config)
script_path = ENV[VAR_CUSTOM_INIT_SCRIPT]
inform("Environment variable #{VAR_CUSTOM_INIT_SCRIPT}") { "'#{script_path}'" }
return if script_path.nil?
return if script_path.empty?

script_pathname = Pathname.getwd + script_path
assure("Script at #{VAR_CUSTOM_INIT_SCRIPT} exists") { script_pathname.exist? }

assure_multiline("Running #{script_pathname} with sh in libraries working dir") do
Dir.chdir(@backend.lib_dir) do
IO.popen(["/bin/sh", script_pathname.to_s], err: [:child, :out]) do |io|
io.each_line { |line| puts " #{line}" }
end
end
end
end

# Unit test procedure
def perform_unit_tests(cpp_library, file_config)
if @cli_options[:skip_unittests]
inform("Skipping unit tests") { "as requested via command line" }
Expand Down Expand Up @@ -394,6 +421,9 @@ def perform_example_compilation_tests(cpp_library, config)
@backend = ArduinoCI::ArduinoInstallation.autolocate!
inform("Located arduino-cli binary") { @backend.binary_path.to_s }

# run any library init scripts from the library itself.
perform_custom_initialization(config)

# initialize library under test
cpp_library_path = Pathname.new(".")
cpp_library = assure("Installing library under test") do
Expand Down

2 comments on commit c6f4d73

@jgfoster
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just stumbled on this and wanted to say it makes installing custom libraries very elegant. Thanks!

@ianfixes
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll enjoy #278

Please sign in to comment.