From dea162e5447d85686d5bcd45d8d7d853525b342c Mon Sep 17 00:00:00 2001 From: Santiago Rodriguez <46354312+santiagorodriguez96@users.noreply.github.com> Date: Mon, 22 Jun 2026 13:23:54 -0300 Subject: [PATCH 1/2] ci: test against different openssl versions --- .github/actions/install-openssl/action.yml | 55 +++++++++++ .github/actions/install-ruby/action.yml | 82 +++++++++++++++ .github/workflows/build.yml | 110 +++++++++++---------- 3 files changed, 194 insertions(+), 53 deletions(-) create mode 100644 .github/actions/install-openssl/action.yml create mode 100644 .github/actions/install-ruby/action.yml diff --git a/.github/actions/install-openssl/action.yml b/.github/actions/install-openssl/action.yml new file mode 100644 index 0000000..18deda2 --- /dev/null +++ b/.github/actions/install-openssl/action.yml @@ -0,0 +1,55 @@ +name: Install OpenSSL + +inputs: + version: + description: 'The version of OpenSSL to install' + required: true + +runs: + using: 'composite' + steps: + - name: Restore cached OpenSSL library + id: cache-openssl-restore + uses: actions/cache/restore@v4 + with: + path: ~/openssl + key: openssl-${{ inputs.version }} + + - name: Compile OpenSSL library + if: steps.cache-openssl-restore.outputs.cache-hit != 'true' + shell: bash + run: | + mkdir -p tmp/build-openssl && cd tmp/build-openssl + case ${{ inputs.version }} in + 1.1.*) + OPENSSL_COMMIT=OpenSSL_ + OPENSSL_COMMIT+=$(echo ${{ inputs.version }} | sed -e 's/\./_/g') + git clone -b $OPENSSL_COMMIT --depth 1 https://github.com/openssl/openssl.git . + echo "Git commit: $(git rev-parse HEAD)" + ./Configure --prefix=$HOME/openssl --libdir=lib linux-x86_64 + make depend && make -j4 && make install_sw + ;; + 3.*) + OPENSSL_COMMIT=openssl- + OPENSSL_COMMIT+=$(echo ${{ inputs.version }}) + git clone -b $OPENSSL_COMMIT --depth 1 https://github.com/openssl/openssl.git . + echo "Git commit: $(git rev-parse HEAD)" + if [[ ${{ inputs.version }} == 3.5* ]]; then + ./Configure --prefix=$HOME/openssl --libdir=lib enable-fips no-tests no-legacy + else + ./Configure --prefix=$HOME/openssl --libdir=lib enable-fips no-tests + fi + make -j4 && make install_sw && make install_fips + ;; + *) + echo "Don't know how to build OpenSSL ${{ inputs.version }}" + ;; + esac + + - name: Save OpenSSL library cache + if: steps.cache-openssl-restore.outputs.cache-hit != 'true' + id: cache-openssl-save + uses: actions/cache/save@v4 + with: + path: ~/openssl + key: ${{ steps.cache-openssl-restore.outputs.cache-primary-key }} diff --git a/.github/actions/install-ruby/action.yml b/.github/actions/install-ruby/action.yml new file mode 100644 index 0000000..a75c77a --- /dev/null +++ b/.github/actions/install-ruby/action.yml @@ -0,0 +1,82 @@ +name: Install Ruby + +inputs: + version: + description: 'The version of Ruby to install' + required: true + openssl-version: + description: 'The version of OpenSSL used' + required: true + +runs: + using: 'composite' + steps: + - name: Restore cached Ruby installation + id: cache-ruby-restore + uses: actions/cache/restore@v4 + with: + path: ~/rubies/ruby-${{ inputs.version }} + key: ruby-${{ inputs.version }}-with-openssl-${{ inputs.openssl-version }} + + - name: Install Ruby + if: steps.cache-ruby-restore.outputs.cache-hit != 'true' + shell: bash + run: | + latest_patch=$(curl -s https://cache.ruby-lang.org/pub/ruby/${{ inputs.version }}/ \ + | grep -oP "ruby-${{ inputs.version }}\.\d+\.tar\.xz" \ + | grep -oP "\d+(?=\.tar\.xz)" \ + | sort -V | tail -n 1) + wget https://cache.ruby-lang.org/pub/ruby/${{ inputs.version }}/ruby-${{ inputs.version }}.${latest_patch}.tar.xz + tar -xJvf ruby-${{ inputs.version }}.${latest_patch}.tar.xz + cd ruby-${{ inputs.version }}.${latest_patch} + ./configure --prefix=$HOME/rubies/ruby-${{ inputs.version }} --with-openssl-dir=$HOME/openssl + make + make install + + - name: Update PATH + shell: bash + run: | + echo "~/rubies/ruby-${{ inputs.version }}/bin" >> $GITHUB_PATH + + - name: Install Bundler + shell: bash + run: | + case ${{ inputs.version }} in + 2.7* | 3.*) + echo "Skipping Bundler installation for Ruby ${{ inputs.version }}" + ;; + 2.4* | 2.5* | 2.6*) + gem install bundler -v '~> 2.3.0' + ;; + *) + echo "Don't know how to install Bundler for Ruby ${{ inputs.version }}" + ;; + esac + + - name: Save Ruby installation cache + if: steps.cache-ruby-restore.outputs.cache-hit != 'true' + id: cache-ruby-save + uses: actions/cache/save@v4 + with: + path: ~/rubies/ruby-${{ inputs.version }} + key: ${{ steps.cache-ruby-restore.outputs.cache-primary-key }} + + - name: Cache Bundler Install + id: cache-bundler-restore + uses: actions/cache/restore@v4 + with: + path: ~/bundler/cache + key: bundler-ruby-${{ inputs.version }}-${{ inputs.openssl-version }}-${{ hashFiles(env.BUNDLE_GEMFILE, 'openssl-signature_algorithm.gemspec') }} + + - name: Install dependencies + shell: bash + run: | + bundle config set --local path ~/bundler/cache + bundle install + + - name: Save Bundler Install cache + id: cache-bundler-save + uses: actions/cache/save@v4 + with: + path: ~/bundler/cache + key: ${{ steps.cache-bundler-restore.outputs.cache-primary-key }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 23eb34b..3cc6fbc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,73 +26,77 @@ jobs: - name: Lint code for consistent style run: bundle exec rubocop -f github test: + name: 'Ruby ${{ matrix.ruby-version }} | ${{ matrix.gemfile }} | OpenSSL ${{ matrix.openssl }}' runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: ruby-version: - - 3.4 - - 3.3 - - 3.2 - - 3.1 - - '3.0' - - 2.7 - - 2.6 - - 2.5 - - 2.4 + - '3.4' + - '3.3' + - '3.2' + - '3.1' gemfile: - openssl_3_3 - openssl_3_2 - openssl_3_1 - openssl_3_0 - - openssl_2_2 - - openssl_2_1 - exclude: - - ruby-version: '2.4' - gemfile: openssl_3_0 - - ruby-version: '2.5' - gemfile: openssl_3_0 - - ruby-version: '2.4' - gemfile: openssl_3_1 - - ruby-version: '2.5' - gemfile: openssl_3_1 - - ruby-version: '2.4' - gemfile: openssl_3_2 - - ruby-version: '2.5' - gemfile: openssl_3_2 - - ruby-version: '2.6' - gemfile: openssl_3_2 - - ruby-version: '2.4' - gemfile: openssl_3_3 - - ruby-version: '2.5' - gemfile: openssl_3_3 - - ruby-version: '2.6' - gemfile: openssl_3_3 - - ruby-version: '3.1' - gemfile: openssl_2_1 - - ruby-version: '3.1' - gemfile: openssl_2_2 - - ruby-version: '3.2' - gemfile: openssl_2_1 - - ruby-version: '3.2' - gemfile: openssl_2_2 - - ruby-version: '3.3' - gemfile: openssl_2_1 - - ruby-version: '3.3' - gemfile: openssl_2_2 - - ruby-version: '3.4' - gemfile: openssl_2_1 - - ruby-version: '3.4' - gemfile: openssl_2_2 + openssl: + - '3.6.0' + - '3.5.4' + - '3.4.3' + - '3.3.5' + - '3.2.6' + - '3.1.8' + - '3.0.18' + - '1.1.1w' + include: + - { ruby-version: '3.4', gemfile: openssl_2_2, openssl: '1.1.1w' } + - { ruby-version: '3.4', gemfile: openssl_2_1, openssl: '1.1.1w' } + - { ruby-version: '3.3', gemfile: openssl_2_2, openssl: '1.1.1w' } + - { ruby-version: '3.3', gemfile: openssl_2_1, openssl: '1.1.1w' } + - { ruby-version: '3.2', gemfile: openssl_2_2, openssl: '1.1.1w' } + - { ruby-version: '3.2', gemfile: openssl_2_1, openssl: '1.1.1w' } + - { ruby-version: '3.1', gemfile: openssl_2_2, openssl: '1.1.1w' } + - { ruby-version: '3.1', gemfile: openssl_2_1, openssl: '1.1.1w' } + # Legacy Rubies (<= 3.0) only build against OpenSSL 1.1.1w, since their + # bundled openssl extension caps at 1.1.1. Each Ruby is paired with every + # openssl gem version it supports. + - { ruby-version: '3.0', gemfile: openssl_3_3, openssl: '1.1.1w' } + - { ruby-version: '3.0', gemfile: openssl_3_2, openssl: '1.1.1w' } + - { ruby-version: '3.0', gemfile: openssl_3_1, openssl: '1.1.1w' } + - { ruby-version: '3.0', gemfile: openssl_3_0, openssl: '1.1.1w' } + - { ruby-version: '3.0', gemfile: openssl_2_2, openssl: '1.1.1w' } + - { ruby-version: '3.0', gemfile: openssl_2_1, openssl: '1.1.1w' } + - { ruby-version: '2.7', gemfile: openssl_3_3, openssl: '1.1.1w' } + - { ruby-version: '2.7', gemfile: openssl_3_2, openssl: '1.1.1w' } + - { ruby-version: '2.7', gemfile: openssl_3_1, openssl: '1.1.1w' } + - { ruby-version: '2.7', gemfile: openssl_3_0, openssl: '1.1.1w' } + - { ruby-version: '2.7', gemfile: openssl_2_2, openssl: '1.1.1w' } + - { ruby-version: '2.7', gemfile: openssl_2_1, openssl: '1.1.1w' } + - { ruby-version: '2.6', gemfile: openssl_3_1, openssl: '1.1.1w' } + - { ruby-version: '2.6', gemfile: openssl_3_0, openssl: '1.1.1w' } + - { ruby-version: '2.6', gemfile: openssl_2_2, openssl: '1.1.1w' } + - { ruby-version: '2.6', gemfile: openssl_2_1, openssl: '1.1.1w' } + - { ruby-version: '2.5', gemfile: openssl_2_2, openssl: '1.1.1w' } + - { ruby-version: '2.5', gemfile: openssl_2_1, openssl: '1.1.1w' } + - { ruby-version: '2.4', gemfile: openssl_2_2, openssl: '1.1.1w' } + - { ruby-version: '2.4', gemfile: openssl_2_1, openssl: '1.1.1w' } env: BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile steps: - uses: actions/checkout@v2 - - run: rm Gemfile.lock - - name: Set up Ruby ${{ matrix.ruby }} - uses: ruby/setup-ruby@v1 + + - name: Install OpenSSL + uses: ./.github/actions/install-openssl + with: + version: ${{ matrix.openssl }} + + - name: Set up Ruby ${{ matrix.ruby-version }} + uses: ./.github/actions/install-ruby with: - ruby-version: ${{ matrix.ruby-version }} - bundler-cache: true + version: ${{ matrix.ruby-version }} + openssl-version: ${{ matrix.openssl }} + - name: Run tests run: bundle exec rspec From ef439e499f2dc5c5cf610edb4d1a92d5250f063a Mon Sep 17 00:00:00 2001 From: Santiago Rodriguez <46354312+santiagorodriguez96@users.noreply.github.com> Date: Mon, 22 Jun 2026 15:39:05 -0300 Subject: [PATCH 2/2] ci: fix `bundle install` errors for ruby 2.4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Ruby 2.4 job fails with: ``` ERROR: SSL verification error at depth 1: unable to get local issuer certificate (20) ERROR: You must add /OU=GlobalSign Root CA - R3/... to your local trusted store ERROR: Could not find a valid gem 'bundler' (~> 2.3.0) ... certificate verify failed ``` The problem is that `install-openssl` compiles OpenSSL with `--prefix=$HOME/openssl`, so its default cert dir (`OPENSSLDIR`) is `$HOME/openssl/ssl`, which is empty – the build has no CA trust store. Ruby is then built against that OpenSSL (`--with-openssl-dir=$HOME/openssl`), so every TLS call (`gem install`, `bundle install`) can't validate `rubygems.org's` `GlobalSign` chain. Ubuntu's real CA bundle lives at `/etc/ssl/certs/` but the custom OpenSSL never looks there. --- .github/actions/install-ruby/action.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/actions/install-ruby/action.yml b/.github/actions/install-ruby/action.yml index a75c77a..3eb83ce 100644 --- a/.github/actions/install-ruby/action.yml +++ b/.github/actions/install-ruby/action.yml @@ -38,6 +38,13 @@ runs: run: | echo "~/rubies/ruby-${{ inputs.version }}/bin" >> $GITHUB_PATH + - name: Trust system CA certificates (Ruby 2.4's bundled RubyGems lacks current roots) + if: inputs.version == '2.4' + shell: bash + run: | + echo "SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt" >> $GITHUB_ENV + echo "SSL_CERT_DIR=/etc/ssl/certs" >> $GITHUB_ENV + - name: Install Bundler shell: bash run: |