diff --git a/.github/workflows/nightly_ci_build.yml b/.github/workflows/nightly_ci_build.yml index d847c05..3cdc448 100644 --- a/.github/workflows/nightly_ci_build.yml +++ b/.github/workflows/nightly_ci_build.yml @@ -3,30 +3,28 @@ name: Scenario-gem CI on: workflow_dispatch: - # push: + push: schedule: # https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule # 5 am UTC (11pm MDT the day before) every weekday night in MDT - cron: '21 5 * * 2-6' - pull_request: - types: [review_requested] env: - # This env var should enforce develop branch of all dependencies + # This env var will enforce develop branch of all dependencies FAVOR_LOCAL_GEMS: true GEM_DEVELOPER_KEY: ${{ secrets.GEM_DEVELOPER_KEY }} jobs: weeknight-tests: - # ubuntu-latest works since https://github.com/rbenv/ruby-build/releases/tag/v20220710 (July 10, 2022) - # https://github.com/rbenv/ruby-build/discussions/1940 runs-on: ubuntu-latest container: - image: docker://nrel/openstudio:3.7.0 + image: docker://nrel/openstudio:3.9.0 steps: - uses: actions/checkout@v4 - name: Update gems - run: bundle update + run: | + bundle install + bundle update - name: Run Rspec run: bundle exec rspec - name: Coveralls diff --git a/CHANGELOG.md b/CHANGELOG.md index e21fdd5..ef358e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # URBANopt Scenario Gem +## Version 1.0.0 + +Date Range: 05/06/24 - 01/23/25 + +* Upgrade to OpenStudio 3.9 and Ruby 3.2.2 by @vtnate in https://github.com/urbanopt/urbanopt-scenario-gem/pull/276 +* Fixup openstudio-extension-gem sub bundle errors by @jmarrec in https://github.com/urbanopt/urbanopt-scenario-gem/pull/275 + +### New Contributors + +* @jmarrec made their first contribution in https://github.com/urbanopt/urbanopt-scenario-gem/pull/275 + +**Full Changelog**: https://github.com/urbanopt/urbanopt-scenario-gem/compare/v0.12.0...v1.0.0 + ## Version 0.12.0 Date Range: 01/10/24 - 05/06/24 * Use new version of reporting-gem by @vtnate in https://github.com/urbanopt/urbanopt-scenario-gem/pull/271 @@ -194,7 +207,7 @@ Date Range: 01/15/20 - 03/30/20: - Fixed [#83]( https://github.com/urbanopt/urbanopt-scenario-gem/pull/83 ), add multiple pV - Fixed [#88]( https://github.com/urbanopt/urbanopt-scenario-gem/pull/88 ), add units to CSV reports - Fixed [#89]( https://github.com/urbanopt/urbanopt-scenario-gem/pull/89 ), created Save feature report method -- Fixed [#91]( https://github.com/urbanopt/urbanopt-scenario-gem/pull/91 ), add total_costruction_cost to reports +- Fixed [#91]( https://github.com/urbanopt/urbanopt-scenario-gem/pull/91 ), add total_construction_cost to reports - Fixed [#95]( https://github.com/urbanopt/urbanopt-scenario-gem/issues/95 ), list datapoint failures - Fixed [#98]( https://github.com/urbanopt/urbanopt-scenario-gem/pull/98 ), add power, net power, net energy and apparent power to timeseries results - Fixed [#101]( https://github.com/urbanopt/urbanopt-scenario-gem/pull/101 ), fix for unit conversion when timeseries doe not exist diff --git a/Gemfile b/Gemfile index 75353d5..284d263 100644 --- a/Gemfile +++ b/Gemfile @@ -23,7 +23,7 @@ allow_local = ENV['FAVOR_LOCAL_GEMS'] # if allow_local && File.exist?('../urbanopt-core-gem') # gem 'urbanopt-core', path: '../urbanopt-core-gem' # elsif allow_local -# gem 'urbanopt-core', github: 'URBANopt/urbanopt-core-gem', branch: 'os37' +# gem 'urbanopt-core', github: 'URBANopt/urbanopt-core-gem', branch: 'os39' # end # if allow_local && File.exist?('../openstudio-common-measures-gem') diff --git a/LICENSE.md b/LICENSE.md index e495d30..5864b04 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,4 +1,4 @@ -URBANopt (tm), Copyright (c) 2019-2024, Alliance for Sustainable Energy, LLC, and other +URBANopt (tm), Copyright (c) 2019-2025, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/doc_templates/LICENSE.md b/doc_templates/LICENSE.md index e495d30..5864b04 100644 --- a/doc_templates/LICENSE.md +++ b/doc_templates/LICENSE.md @@ -1,4 +1,4 @@ -URBANopt (tm), Copyright (c) 2019-2024, Alliance for Sustainable Energy, LLC, and other +URBANopt (tm), Copyright (c) 2019-2025, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/doc_templates/copyright_erb.txt b/doc_templates/copyright_erb.txt index 9b5ac08..d8bfecc 100644 --- a/doc_templates/copyright_erb.txt +++ b/doc_templates/copyright_erb.txt @@ -1,6 +1,6 @@ <% # ********************************************************************************* - # URBANopt (tm), Copyright (c) 2019-2024, Alliance for Sustainable Energy, LLC, and other + # URBANopt (tm), Copyright (c) 2019-2025, Alliance for Sustainable Energy, LLC, and other # contributors. All rights reserved. # Redistribution and use in source and binary forms, with or without modification, diff --git a/lib/urbanopt/scenario/logger.rb b/lib/urbanopt/scenario/logger.rb index 2311396..32467c2 100644 --- a/lib/urbanopt/scenario/logger.rb +++ b/lib/urbanopt/scenario/logger.rb @@ -9,7 +9,7 @@ module URBANopt module Scenario @@logger = Logger.new($stdout) - # Definining class variable "@@logger" to log errors, info and warning messages. + # Defining class variable "@@logger" to log errors, info and warning messages. def self.logger @@logger end diff --git a/lib/urbanopt/scenario/scenario_csv.rb b/lib/urbanopt/scenario/scenario_csv.rb index 7c72e26..f9a6a26 100644 --- a/lib/urbanopt/scenario/scenario_csv.rb +++ b/lib/urbanopt/scenario/scenario_csv.rb @@ -48,21 +48,31 @@ def initialize(name, root_dir, run_dir, feature_file, mapper_files_dir, csv_file # Require all simulation mappers in mapper_files_dir def load_mapper_files # loads default values from extension gem - options = OpenStudio::Extension::RunnerConfig.default_config + @options = OpenStudio::Extension::RunnerConfig.default_config(@root_dir) # check if runner.conf file exists if File.exist?(File.join(@root_dir, OpenStudio::Extension::RunnerConfig::FILENAME)) runner_config = OpenStudio::Extension::RunnerConfig.new(@root_dir) - # use the default values overriden with runner.conf values - options = options.merge(runner_config.options) + # use the default values overridden with runner.conf values where not + # nil nor empty strings + @options = @options.merge(runner_config.options.reject{|k, v| v.nil? || (v.kind_of?(String) && v === '')}) end # bundle path is assigned from the runner.conf if it exists or is assigned in the root_dir - bundle_path = !options.key?(:bundle_install_path) || options[:bundle_install_path] === '' ? File.join(@root_dir, '.bundle/install/') : options[:bundle_install_path] + # if bundle install path is not provided or is empty, it will be placed in root_dir/.bundle/install, otherwise use the provided path + if !@options.key?(:bundle_install_path) || @options[:bundle_install_path] === '' + @options[:bundle_install_path] = File.join(@root_dir, '.bundle/install/') + else + @options[:bundle_install_path]= Pathname.new(@options[:bundle_install_path]).cleanpath.to_s + end + bundle_path = @options[:bundle_install_path] + + puts "Bundle final path is set to: #{bundle_path}" # checks if bundle path doesn't exist or is empty if !Dir.exist?(bundle_path) || Dir.empty?(bundle_path) - # install bundle - OpenStudio::Extension::Runner.new(@root_dir) + Bundler.with_unbundled_env do + OpenStudio::Extension::Runner.new(@root_dir, [], @options) + end end # find all lib dirs in the bundle path and add them to the path diff --git a/lib/urbanopt/scenario/scenario_datapoint_base.rb b/lib/urbanopt/scenario/scenario_datapoint_base.rb index bf3e175..110a5db 100644 --- a/lib/urbanopt/scenario/scenario_datapoint_base.rb +++ b/lib/urbanopt/scenario/scenario_datapoint_base.rb @@ -89,7 +89,7 @@ def create_osw # rubocop: enable Style/EvalWithLocation #:nodoc: ## - # Return true if the datapoint is out of date, false otherwise. Non-existant files are out of date. + # Return true if the datapoint is out of date, false otherwise. Non-existent files are out of date. ## # [return:] _Boolean_ - True if the datapoint is out of date, false otherwise. def out_of_date? diff --git a/lib/urbanopt/scenario/scenario_runner_osw.rb b/lib/urbanopt/scenario/scenario_runner_osw.rb index 5911c8d..902feba 100644 --- a/lib/urbanopt/scenario/scenario_runner_osw.rb +++ b/lib/urbanopt/scenario/scenario_runner_osw.rb @@ -46,11 +46,11 @@ def create_simulation_files(scenario, force_clear = false) ## # Create and run all SimulationFileOSW for Scenario. - # A staged runner is implented to run buildings, then transformers then district systems. + # A staged runner is implemented to run buildings, then transformers then district systems. # - instantiate openstudio runner to run .osw files. # - create simulation files for this scenario. # - get feature_type value from in.osw files - # - cretae 3 groups to store .osw files (+building_osws+ , +transformer_osws+ , +district_system_osws+) + # - create 3 groups to store .osw files (+building_osws+ , +transformer_osws+ , +district_system_osws+) # - add each osw file to its corresponding group id +simulation_dir+ is out_of_date # - Run osw file groups in order and store simulation failure in a array. ## @@ -78,7 +78,7 @@ def run(scenario, force_clear = false, options = {}) # end # end - # cretae 3 groups to store .osw files (+building_osws+ , +transformer_osws+ , +district_system_osws+) + # create 3 groups to store .osw files (+building_osws+ , +transformer_osws+ , +district_system_osws+) building_osws = [] transformer_osws = [] district_system_osws = [] diff --git a/lib/urbanopt/scenario/simulation_dir_base.rb b/lib/urbanopt/scenario/simulation_dir_base.rb index 666bd39..bfbfe99 100644 --- a/lib/urbanopt/scenario/simulation_dir_base.rb +++ b/lib/urbanopt/scenario/simulation_dir_base.rb @@ -30,7 +30,7 @@ def run_dir ## # Return true if the simulation is out of date (input files newer than results), false otherwise. - # Non-existant simulation input files are out of date. + # Non-existent simulation input files are out of date. ## def out_of_date? raise 'out_of_date? is not implemented for SimulationFileBase, override in your class' diff --git a/lib/urbanopt/scenario/simulation_dir_osw.rb b/lib/urbanopt/scenario/simulation_dir_osw.rb index 652c26a..4ad3e8a 100644 --- a/lib/urbanopt/scenario/simulation_dir_osw.rb +++ b/lib/urbanopt/scenario/simulation_dir_osw.rb @@ -110,7 +110,7 @@ def out_osw ## # Return true if the simulation is out of date (input files newer than results), false otherwise. - # Non-existant simulation input files are out of date. + # Non-existent simulation input files are out of date. ## def out_of_date? if !File.exist?(run_dir) diff --git a/lib/urbanopt/scenario/version.rb b/lib/urbanopt/scenario/version.rb index e679646..5f260ee 100644 --- a/lib/urbanopt/scenario/version.rb +++ b/lib/urbanopt/scenario/version.rb @@ -5,6 +5,6 @@ module URBANopt module Scenario - VERSION = '0.12.0'.freeze + VERSION = '1.0.0'.freeze end end diff --git a/spec/files/Gemfile b/spec/files/Gemfile index c75e8bb..54eb916 100644 --- a/spec/files/Gemfile +++ b/spec/files/Gemfile @@ -1,6 +1,6 @@ source 'http://rubygems.org' -ruby '~> 2.7.0' +ruby '3.2.2' # Local gems are useful when developing and integrating the various dependencies. # To favor the use of local gems, set the following environment variable: @@ -26,17 +26,12 @@ allow_local = ENV['FAVOR_LOCAL_GEMS'] # end # -# pin this dependency to avoid unicode_normalize error -gem 'addressable', '2.8.1' -# pin this dependency to avoid using racc dependency (which has native extensions) -gem 'parser', '3.2.2.2' - if allow_local && File.exist?('../openstudio-common-measures-gem') gem 'openstudio-common-measures', path: '../openstudio-common-measures-gem' elsif allow_local gem 'openstudio-common-measures', github: 'NREL/openstudio-common-measures-gem', branch: 'develop' else - gem 'openstudio-common-measures', '~> 0.8.0' + gem 'openstudio-common-measures', '~> 0.11.0' end if allow_local && File.exist?('../openstudio-model-articulation-gem') @@ -44,15 +39,15 @@ if allow_local && File.exist?('../openstudio-model-articulation-gem') elsif allow_local gem 'openstudio-model-articulation', github: 'NREL/openstudio-model-articulation-gem', branch: 'develop' else - gem 'openstudio-model-articulation', '~> 0.8.0' + gem 'openstudio-model-articulation', '~> 0.11.0' end if allow_local && File.exist?('../openstudio-load-flexibility-measures-gem') gem 'openstudio-load-flexibility-measures', path: '../openstudio-load-flexibility-measures-gem' elsif allow_local - gem 'openstudio-load-flexibility-measures', github: 'NREL/openstudio-load-flexibility-measures-gem', branch: 'master' + gem 'openstudio-load-flexibility-measures', github: 'NREL/openstudio-load-flexibility-measures-gem', branch: 'develop' else - gem 'openstudio-load-flexibility-measures', '~> 0.7.0' + gem 'openstudio-load-flexibility-measures', '~> 0.10.0' end if allow_local && File.exist?('../openstudio-ee-gem') @@ -60,7 +55,7 @@ if allow_local && File.exist?('../openstudio-ee-gem') elsif allow_local gem 'openstudio-ee', github: 'NREL/openstudio-ee-gem', branch: 'develop' else - gem 'openstudio-ee', '~> 0.8.0' + gem 'openstudio-ee', '~> 0.11.0' end if allow_local && File.exist?('../openstudio-calibration-gem') @@ -68,7 +63,7 @@ if allow_local && File.exist?('../openstudio-calibration-gem') elsif allow_local gem 'openstudio-calibration', github: 'NREL/openstudio-calibration-gem', branch: 'develop' else - gem 'openstudio-calibration', '~> 0.8.0' + gem 'openstudio-calibration', '~> 0.11.0' end if allow_local && File.exist?('../urbanopt-geojson-gem') @@ -76,7 +71,7 @@ if allow_local && File.exist?('../urbanopt-geojson-gem') elsif allow_local gem 'urbanopt-geojson', github: 'URBANopt/urbanopt-geojson-gem', branch: 'develop' else - gem 'urbanopt-geojson', '~> 0.10.0' + gem 'urbanopt-geojson', '~> 1.0.0' end # NEVER put SCENARIO-GEM in this file...it will make all simulations fail due to the sqlite dependency @@ -87,5 +82,5 @@ if allow_local && File.exist?('../urbanopt-reporting-gem') elsif allow_local gem 'urbanopt-reporting', github: 'URBANopt/urbanopt-reporting-gem', branch: 'develop' else - gem 'urbanopt-reporting', '~> 0.8.0' + gem 'urbanopt-reporting', '~> 1.0.0' end diff --git a/spec/urbanopt/urbanopt_scenario_spec.rb b/spec/urbanopt/urbanopt_scenario_spec.rb index 7382864..8c7b5a6 100644 --- a/spec/urbanopt/urbanopt_scenario_spec.rb +++ b/spec/urbanopt/urbanopt_scenario_spec.rb @@ -7,8 +7,13 @@ require_relative '../files/example_feature_file' require 'json' require 'json-schema' +require 'logger' + RSpec.describe URBANopt::Scenario do - @@logger ||= URBANopt::Reporting::DefaultReports.logger + + let(:logger) { Logger.new($stdout) } + + root_dir = (Pathname(__FILE__).dirname.parent / 'test').cleanpath it 'has a version number' do expect(URBANopt::Scenario::VERSION).not_to be nil @@ -17,8 +22,8 @@ it 'has a logger' do expect(URBANopt::Scenario.logger).not_to be nil current_level = URBANopt::Scenario.logger.level - URBANopt::Scenario.logger.level = Logger::DEBUG - expect(URBANopt::Scenario.logger.level).to eq Logger::DEBUG + URBANopt::Scenario.logger.level = Logger::ERROR + expect(URBANopt::Scenario.logger.level).to eq Logger::ERROR URBANopt::Scenario.logger.level = current_level end @@ -26,24 +31,23 @@ name = 'example_scenario' # copy all files into test directory - root_dir = File.join(File.dirname(__FILE__), '../test') Dir.mkdir(root_dir) unless File.exist?(root_dir) - run_dir = File.join(File.dirname(__FILE__), '../test/example_scenario/') - FileUtils.cp(File.join(File.dirname(__FILE__), '../files/example_feature_file.json'), File.join(File.dirname(__FILE__), '../test/example_feature_file.json')) - feature_file_path = File.join(File.dirname(__FILE__), '../test/example_feature_file.json') - FileUtils.cp_r(File.join(File.dirname(__FILE__), '../files/mappers'), File.join(File.dirname(__FILE__), '../test/mappers'), remove_destination: true) - FileUtils.cp_r(File.join(File.dirname(__FILE__), '../files/weather'), File.join(File.dirname(__FILE__), '../test/weather'), remove_destination: true) - mapper_files_dir = File.join(File.dirname(__FILE__), '../test/mappers/') - FileUtils.cp(File.join(File.dirname(__FILE__), '../files/example_scenario.csv'), File.join(File.dirname(__FILE__), '../test/example_scenario.csv')) - csv_file = File.join(File.dirname(__FILE__), '../test/example_scenario.csv') + run_dir = root_dir / 'example_scenario/' + FileUtils.cp(root_dir.parent / 'files' / 'example_feature_file.json', root_dir / 'example_feature_file.json') + feature_file_path = root_dir / 'example_feature_file.json' + FileUtils.cp_r(root_dir.parent / 'files' / 'mappers', root_dir.parent / 'test' / 'mappers', remove_destination: true) + FileUtils.cp_r(root_dir.parent / 'files' / 'weather', root_dir.parent / 'test' / 'weather', remove_destination: true) + mapper_files_dir = root_dir / 'mappers/' + FileUtils.cp(root_dir.parent / 'files' / 'example_scenario.csv', root_dir / 'example_scenario.csv') + csv_file = root_dir / 'example_scenario.csv' num_header_rows = 1 - FileUtils.cp(File.join(File.dirname(__FILE__), '../files/Gemfile'), File.join(File.dirname(__FILE__), '../test/Gemfile')) + FileUtils.cp(root_dir.parent / 'files' / 'Gemfile', root_dir / 'Gemfile') # write a runner.conf in project dir - options = { gemfile_path: File.join(File.dirname(__FILE__), '../test/Gemfile'), bundle_install_path: File.join(File.dirname(__FILE__), '../test/.bundle/install') } + options = { gemfile_path: root_dir / 'Gemfile', bundle_install_path: root_dir / '.bundle' / 'install' } File.open(File.join(root_dir, 'runner.conf'), 'w') do |f| - f.write(options.to_json) + f.write(JSON.pretty_generate(options)) end feature_file = ExampleFeatureFile.new(feature_file_path) @@ -92,7 +96,7 @@ expect(File.exist?(simulation_dirs[2].run_dir)).to be true # pass Gemfile and bundle paths to extension gem runner, otherwise it will use this gem's and that doesn't work b/c of native gems - options = { gemfile_path: File.join(File.dirname(__FILE__), '../test/Gemfile'), bundle_install_path: File.join(File.dirname(__FILE__), '../test/.bundle/install'), skip_config: false } + options = { gemfile_path: root_dir / 'Gemfile', bundle_install_path: root_dir / '.bundle' / 'install', skip_config: false } simulation_dirs = scenario_runner.run(scenario, false, options) if clear_results expect(simulation_dirs.size).to eq(3) @@ -185,10 +189,10 @@ # Get scenario schema hash schema = validator.schema - # Read scenario json file and validated againt schema + # Read scenario json file and validated against schema scenario_json = JSON.parse(File.read(scenario_json_file)) - @@logger.info("Schema Validation Errors: #{JSON::Validator.fully_validate(schema, scenario_json)}") + logger.info("Schema Validation Errors: #{JSON::Validator.fully_validate(schema, scenario_json)}") expect(JSON::Validator.fully_validate(schema, scenario_json).empty?).to be true # close json file @@ -205,7 +209,7 @@ scenario_csv_schema_headers = validator.csv_headers expect((scenario_csv_headers_with_no_units & scenario_csv_schema_headers)).to eq(scenario_csv_headers_with_no_units) - # Read feature_reprot json file and validate against schema + # Read feature_report json file and validate against schema Dir["#{File.dirname(__FILE__)}/../**/*default_feature_reports.json"].each do |json_file| feature_json = JSON.parse(File.read(json_file)) expect(JSON::Validator.fully_validate(schema[:definitions][:FeatureReport][:properties], feature_json).empty?).to be true @@ -214,8 +218,8 @@ it 'can integrate opendss results' do # generate opendss results for testing - opendss_results_source = File.join(File.dirname(__FILE__), '../files/opendss_outputs/') - opendss_results_destination = File.join(File.dirname(__FILE__), '../test/example_scenario') + opendss_results_source = root_dir.parent / 'files' / 'opendss_outputs/' + opendss_results_destination = root_dir / 'example_scenario' FileUtils.copy_entry opendss_results_source, opendss_results_destination # post_process opendss results opendss_post_processor = URBANopt::Scenario::OpenDSSPostProcessor.new($scenario_result, 'opendss') @@ -224,8 +228,8 @@ it 'can integrate disco results' do # generate disco results for testing - disco_results_source = File.join(File.dirname(__FILE__), '../files/disco_outputs/') - disco_results_destination = File.join(File.dirname(__FILE__), '../test/example_scenario') + disco_results_source = root_dir.parent / 'files' / 'disco_outputs/' + disco_results_destination = root_dir / 'example_scenario' FileUtils.copy_entry disco_results_source, disco_results_destination # post_process disco results disco_post_processor = URBANopt::Scenario::DISCOPostProcessor.new($scenario_result, 'disco') diff --git a/spec/vis_test/baseline_scenario/scenarioData.js b/spec/vis_test/baseline_scenario/scenarioData.js index e0b83c7..a474c07 100644 --- a/spec/vis_test/baseline_scenario/scenarioData.js +++ b/spec/vis_test/baseline_scenario/scenarioData.js @@ -1670,8 +1670,7 @@ var scenarioData = [ "Ice Thermal Storage End Fraction": 0.0, "Cooling Coil Ice Thermal Storage End Fraction": 0.0 }, - "qaqc_flags": { - }, + "qaqc_flags": {}, "complete_simulation": true }, { @@ -3945,8 +3944,7 @@ var scenarioData = [ "Net Power": 27935873.47948147, "Net Apparent Power": 31039859.421646073 }, - "qaqc_flags": { - }, + "qaqc_flags": {}, "complete_simulation": true } ]; \ No newline at end of file diff --git a/spec/vis_test/scenarioData.js b/spec/vis_test/scenarioData.js index f44fa19..1620e0f 100644 --- a/spec/vis_test/scenarioData.js +++ b/spec/vis_test/scenarioData.js @@ -500,8 +500,7 @@ var scenarioData = [ "Net Power": 27935873.479511403, "Net Apparent Power": 31039859.421645597 }, - "qaqc_flags": { - }, + "qaqc_flags": {}, "complete_simulation": true } ]; \ No newline at end of file diff --git a/urbanopt-scenario-gem.gemspec b/urbanopt-scenario-gem.gemspec index b0a71df..2133698 100644 --- a/urbanopt-scenario-gem.gemspec +++ b/urbanopt-scenario-gem.gemspec @@ -21,14 +21,14 @@ Gem::Specification.new do |spec| spec.bindir = 'exe' spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ['lib'] - spec.required_ruby_version = '~> 2.7.0' + # We support exactly Ruby v3.2.2 because os-extension requires bundler==2.4.10 and that requires Ruby 3.2.2: https://stdgems.org/bundler/ + # It would be nice to be able to use newer patches of Ruby 3.2, which would require os-extension to relax its dependency on bundler. + spec.required_ruby_version = '3.2.2' - spec.add_development_dependency 'bundler', '~> 2.1' - spec.add_development_dependency 'rake', '~> 13.1' - spec.add_development_dependency 'rspec', '~> 3.12' - spec.add_development_dependency 'simplecov', '~> 0.18.2' - spec.add_development_dependency 'simplecov-lcov', '~> 0.8.0' - spec.add_runtime_dependency 'sqlite3', '~> 1.6.0' - spec.add_runtime_dependency 'urbanopt-core', '~> 0.11.0' - spec.add_runtime_dependency 'urbanopt-reporting', '~> 0.10.0' + spec.add_development_dependency 'rspec', '~> 3.13' + spec.add_development_dependency 'simplecov', '0.22.0' + spec.add_development_dependency 'simplecov-lcov', '0.8.0' + spec.add_runtime_dependency 'sqlite3', '~> 2.0.0' + spec.add_runtime_dependency 'urbanopt-core', '~> 1.0.0' + spec.add_runtime_dependency 'urbanopt-reporting', '~> 1.0.0' end