From 4e78f467a7ac9d2494836602af04a37e6b7752e6 Mon Sep 17 00:00:00 2001 From: Thomas Schmidt Date: Thu, 10 Sep 2026 16:50:24 +0200 Subject: [PATCH 1/2] split test runs into groups --- .github/workflows/ci.yml | 83 ++++++++++++++++++++++++++++++++++++---- spec/rails_helper.rb | 4 +- 2 files changed, 79 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6c2a1bcbb..944745374 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,6 +58,20 @@ jobs: test: runs-on: ubuntu-latest + # The runner is too weak for more than 2 headless Chrome instances, so every job + # keeps 2 processes and the fan out happens over jobs. All jobs must compute the + # same 6 groups, so they must read the same runtime log. Only the coverage job + # writes that cache. + strategy: + fail-fast: false + matrix: + include: + - part: 1 + groups: "1,2" + - part: 2 + groups: "3,4" + - part: 3 + groups: "5,6" #container: # image: ghcr.io/mapforge-org/mapforge-ci-runner:latest services: @@ -71,8 +85,8 @@ jobs: # password: ${{ secrets.DOCKER_TOKEN }} env: RAILS_ENV: test - PARALLEL_TEST_PROCESSORS: ${{ vars.PARALLEL_TEST_PROCESSORS }} COVERAGE: true + CI_PART: ${{ matrix.part }} # turns off the per job coverage minimum SE_AVOID_STATS: true # skip Selenium stats SE_DISABLE_REMOTE_MANAGER: true # skip Selenium plausible telemetry # MONGO_URL is only needed when not running on ubuntu-latest VM @@ -96,8 +110,8 @@ jobs: # caches by Gemfile.lock checksum bundler-cache: true # Share test run timings across CI runs for optimal distribution - - name: Cache spec runtimes - uses: actions/cache@v4 + - name: Restore spec runtimes + uses: actions/cache/restore@v4 with: path: tmp/parallel_runtime_rspec.log key: rspec-runtime-${{ github.run_id }} @@ -107,26 +121,81 @@ jobs: #run: | # bin/rspec --pattern "spec/**/*_spec.rb,engines/**/*_spec.rb" run: | - bin/parallel_rspec spec engines + # --group-by runtime reads the log without a rescue, so it must exist + mkdir -p tmp && touch tmp/parallel_runtime_rspec.log + bin/parallel_rspec spec engines -n 6 \ + --group-by runtime --allowed-missing 100 --only-group ${{ matrix.groups }} shell: bash + - name: Upload partial results + if: always() + uses: actions/upload-artifact@v4 + with: + name: part-${{ matrix.part }} + include-hidden-files: true + path: | + coverage/.resultset.json + tmp/parallel_runtime_rspec.log - name: Upload screenshots if: failure() uses: actions/upload-artifact@v4 with: - name: screenshots + name: screenshots-${{ matrix.part }} path: ./tmp/capybara - name: Upload logs if: failure() uses: actions/upload-artifact@v4 with: - name: rails-logs + name: rails-logs-${{ matrix.part }} path: ./log/test.log + + coverage: + needs: test + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Update package lists + run: sudo apt-get update + # rgeo-proj4 does not build without it + - name: Install dependencies + run: sudo apt-get install --no-install-recommends -y libproj-dev libimlib2-dev + - name: Install Ruby and gems + uses: ruby/setup-ruby@v1 + with: + # caches by Gemfile.lock checksum + bundler-cache: true + - name: Download partial results + uses: actions/download-artifact@v4 + with: + pattern: part-* + path: parts + # Every job only knows the coverage of its own groups. The minimum in + # spec/rails_helper.rb therefore cannot apply. Enforce it over the merged data. + - name: Check merged coverage + run: | + bundle exec ruby -e ' + require "simplecov" + SimpleCov.collate Dir["parts/*/coverage/.resultset.json"], "rails" do + minimum_coverage 100 + skip "app/jobs/application_job.rb" + skip "lib/tasks" + end + ' - name: Upload coverage - if: failure() + if: always() uses: actions/upload-artifact@v4 with: name: coverage path: ./coverage + - name: Merge spec runtimes + run: | + mkdir -p tmp + cat parts/*/tmp/parallel_runtime_rspec.log > tmp/parallel_runtime_rspec.log + - name: Save spec runtimes + uses: actions/cache/save@v4 + with: + path: tmp/parallel_runtime_rspec.log + key: rspec-runtime-${{ github.run_id }} # - name: Coveralls # uses: coverallsapp/github-action@v2 # with: diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index ddbdbab7e..d6b4fb883 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -1,7 +1,9 @@ # This file is copied to spec/ when you run 'rails generate rspec:install' if ENV["COVERAGE"] == "true" require "simplecov" - SimpleCov.minimum_coverage 100 + # CI splits the suite over jobs. A single job covers only its own groups, so the + # minimum applies to the merged report instead, see the coverage job in ci.yml. + SimpleCov.minimum_coverage 100 unless ENV["CI_PART"] SimpleCov.start "rails" do skip "app/jobs/application_job.rb" skip "lib/tasks" From 15e85573da31176773c767740ed222b8395d8a48 Mon Sep 17 00:00:00 2001 From: Thomas Schmidt Date: Thu, 10 Sep 2026 17:37:13 +0200 Subject: [PATCH 2/2] add webmock to block http requests from rails in tests --- Gemfile | 1 + Gemfile.lock | 9 +++++++++ spec/rails_helper.rb | 6 ++++++ 3 files changed, 16 insertions(+) diff --git a/Gemfile b/Gemfile index b6ff0cebf..7c1ccf241 100644 --- a/Gemfile +++ b/Gemfile @@ -110,4 +110,5 @@ group :test do gem "cuprite" gem "capybara_mock" gem "table_print" + gem "webmock" end diff --git a/Gemfile.lock b/Gemfile.lock index dea24a883..6c87185d9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -162,6 +162,9 @@ GEM fiber-annotation fiber-local (~> 1.1) json + crack (1.0.1) + bigdecimal + rexml crass (1.0.7) csv (3.3.5) cuprite (0.17) @@ -280,6 +283,7 @@ GEM temple (>= 0.8.2) thor tilt + hashdiff (1.2.1) hashie (5.1.0) logger i18n (1.15.2) @@ -687,6 +691,10 @@ GEM actionview (>= 8.0.0) bindex (>= 0.4.0) railties (>= 8.0.0) + webmock (3.26.4) + addressable (>= 2.8.0) + crack (>= 0.3.2) + hashdiff (>= 0.4.0, < 2.0.0) webrick (1.9.2) websocket (1.2.11) websocket-driver (0.8.2) @@ -787,6 +795,7 @@ DEPENDENCIES thruster turbo-rails web-console + webmock yabeda-prometheus yabeda-puma-plugin yabeda-rails diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index d6b4fb883..3e5de1e94 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -26,6 +26,12 @@ require "capybara-screenshot/rspec" require "mongoid-rspec" require "capybara_mock/rspec" +require "webmock/rspec" + +# host-resolver-rules in spec/support/capybara.rb isolates Chrome. This isolates the Rails +# process the same way, so a missed stub fails loudly instead of reaching the real network. +# The Capybara server and the Chrome debug port both listen on localhost. +WebMock.disable_net_connect!(allow_localhost: true) # Requires supporting ruby files with custom matchers and macros, etc, in # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are