From ab36222df3629a6b5798ae10b29525d793bab0b9 Mon Sep 17 00:00:00 2001 From: Facundo Farias Date: Wed, 16 Sep 2026 08:45:01 +0200 Subject: [PATCH 1/2] Replace dead Travis config with GitHub Actions This repo has never run tests. The only CI config was a .travis.yml pinning Ruby 2.2.3 and bundler 1.10.6, and it was dead three times over: Travis was never connected to this fork (created 2026-08-20; a fork does not inherit the upstream's CI integration), travis-ci.org shut down in 2021, and Ruby 2.2.3 is long EOL. The PR that prompted this had zero check runs and zero registered workflows. The consequence was not theoretical. The suite could not even load -- `extend Forwardable` with nothing requiring forwardable -- and once that was fixed, 14 of 73 examples failed. Nobody could have known. Adds a workflow that runs rspec on two rubies: 2.7 (ubuntu-22.04) -- what DeployHQ runs today. Gates. 3.4 (ubuntu-24.04) -- where the app is heading. Advisory via continue-on-error, so a failure there cannot block a fix for the Ruby actually in production. Promote to required once consumers have moved. ubuntu-22.04 is required for 2.7 specifically: setup-ruby ships no 2.7 build for ubuntu-24.04. Two details the workflow has to get right: - The suite is NOT hermetic. spec_helper purges real queues through Bunny, so a RabbitMQ service container has to be healthy before any example runs. - The broker user is deliberately NOT `guest`. RabbitMQ restricts guest to loopback, and a service container is reached over the docker bridge, so guest authentication is refused. The workflow provisions a `leveret` user instead. That last point needs spec_helper to be configurable, so it now reads LEVERET_AMQP_URL and falls back to the same amqp://guest:guest@localhost:5672 developers already use. Local runs are unchanged; verified both paths. bundler-cache is off on purpose: this gem ships no Gemfile.lock, so there is no stable key to cache against, and the dependency set is small. Verified locally on 2.7.8 with and without LEVERET_AMQP_URL set: 73 examples, 0 failures both ways. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/ci.yml | 64 ++++++++++++++++++++++++++++++++++++++++ .travis.yml | 4 --- spec/spec_helper.rb | 6 ++++ 3 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..22ce3e3 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,64 @@ +name: CI + +on: + push: + branches: [master] + pull_request: + +jobs: + rspec: + name: rspec (ruby ${{ matrix.ruby }})${{ matrix.advisory && ' [advisory]' || '' }} + runs-on: ${{ matrix.os }} + # 3.4 reports but does not gate, so a failure there cannot block a fix for the 2.7 + # that actually runs in production. Promote it to required once consumers have moved. + continue-on-error: ${{ matrix.advisory || false }} + + strategy: + fail-fast: false + matrix: + include: + # The Ruby DeployHQ runs today. This one gates. + - ruby: '2.7' + os: ubuntu-22.04 # setup-ruby ships no 2.7 build for ubuntu-24.04 + # Where the app is heading; advisory until that upgrade lands. + - ruby: '3.4' + os: ubuntu-24.04 + advisory: true + + services: + rabbitmq: + # The suite is not hermetic -- spec_helper purges real queues through Bunny, so a + # broker has to be up before any example runs. + image: rabbitmq:3-management-alpine + ports: + - 5672:5672 + env: + # NOT guest. RabbitMQ restricts guest to loopback, and a service container is + # reached over the docker bridge, so guest authentication is refused. + RABBITMQ_DEFAULT_USER: leveret + RABBITMQ_DEFAULT_PASS: leveret + options: >- + --health-cmd "rabbitmq-diagnostics -q ping" + --health-interval 5s + --health-timeout 5s + --health-retries 20 + + steps: + - uses: actions/checkout@v4 + + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + # No bundler-cache: this gem deliberately ships no Gemfile.lock, so there is no + # stable key to cache against. The dependency set is small. + bundler-cache: false + + - name: Install dependencies + run: | + gem install bundler --no-document + bundle install --jobs 4 --retry 3 + + - name: rspec + env: + LEVERET_AMQP_URL: amqp://leveret:leveret@localhost:5672 + run: bundle exec rspec --format documentation diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 6fb8618..0000000 --- a/.travis.yml +++ /dev/null @@ -1,4 +0,0 @@ -language: ruby -rvm: - - 2.2.3 -before_install: gem install bundler -v 1.10.6 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 99626ba..e057d0d 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,5 +1,8 @@ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) require 'leveret' +# Three spec files build doubles with OpenStruct. ostruct is no longer loaded implicitly, so +# without this every example in those files errors before it runs -- 14 of them. +require 'ostruct' Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].each { |f| require f } @@ -8,6 +11,9 @@ c.before(:all) do Leveret.configure do |conf| + # Overridable so CI can point at a broker that does not accept the loopback-only + # `guest` account. Defaults to the same local broker developers already use. + conf.amqp = ENV.fetch('LEVERET_AMQP_URL', 'amqp://guest:guest@localhost:5672') conf.log_level = Logger::ERROR conf.queue_name_prefix = 'leveret_test_queue' conf.default_queue_name = 'test' From 0e6d3a7b000ca0c4cf1263874199ff5f1513d871 Mon Sep 17 00:00:00 2001 From: Facundo Farias Date: Wed, 16 Sep 2026 08:56:20 +0200 Subject: [PATCH 2/2] Pin bundler per Ruby so the 2.7 job can install it The 2.7 job failed at Install dependencies, before a single spec ran: The last version of bundler (>= 0) to support your Ruby & RubyGems was 2.4.22 bundler requires Ruby version >= 3.2.0. The current ruby version is 2.7.8.225 `gem install bundler` with no constraint resolves to the newest release, which now requires Ruby >= 3.2. On 2.7 it cannot install at all. Pin it per Ruby through setup-ruby's own `bundler` input rather than a bare `gem install`, so the version is fixed by the matrix instead of resolved at run time: 2.4.22 on 2.7, latest on 3.4. That 2.4.22 is the same pin the consuming app documents as the last line supporting Ruby 2.7 -- and specifically not 1.17.3, which has a default-gem activation bug that has caused production deploy outages there. Also prints `bundle --version` before installing, so the next failure of this shape is one line of log rather than an inference. The 3.4 job already passed on the previous run -- 73 examples, 0 failures against the RabbitMQ service container -- so the service, the non-guest broker user and LEVERET_AMQP_URL are all confirmed working. Only bundler was wrong. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/ci.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 22ce3e3..b9584d5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,9 +20,15 @@ jobs: # The Ruby DeployHQ runs today. This one gates. - ruby: '2.7' os: ubuntu-22.04 # setup-ruby ships no 2.7 build for ubuntu-24.04 + # 2.4.22 is the last bundler line that supports Ruby 2.7; anything newer + # requires >= 3.2 and fails to install. This is the same pin the consuming + # app documents. Do NOT drop to 1.17.3 -- it has a default-gem activation + # bug that has caused production deploy outages there. + bundler: '2.4.22' # Where the app is heading; advisory until that upgrade lands. - ruby: '3.4' os: ubuntu-24.04 + bundler: 'latest' advisory: true services: @@ -49,13 +55,17 @@ jobs: - uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} + # Let setup-ruby install bundler, so the version is pinned per Ruby (see matrix) + # rather than resolved at run time. A bare `gem install bundler` picks the newest + # release, which on 2.7 is one that refuses to install. + bundler: ${{ matrix.bundler }} # No bundler-cache: this gem deliberately ships no Gemfile.lock, so there is no # stable key to cache against. The dependency set is small. bundler-cache: false - name: Install dependencies run: | - gem install bundler --no-document + bundle --version bundle install --jobs 4 --retry 3 - name: rspec