Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions .github/workflows/cibuildgem.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
name: "Package and release gems with precompiled binaries"
on:
workflow_dispatch:
inputs:
release:
description: "If the whole build passes on all platforms, release the gems on RubyGems.org"
required: false
type: boolean
default: false
jobs:
compile:
timeout-minutes: 20
name: "Cross compile the gem on different ruby versions"
strategy:
matrix:
os: ["macos-latest", "ubuntu-22.04"]
runs-on: "${{ matrix.os }}"
steps:
- name: "Checkout code"
uses: "actions/checkout@v5"
- name: "Setup Ruby"
uses: "ruby/setup-ruby@v1"
with:
ruby-version: "3.1.7"
bundler-cache: true
- name: "Run cibuildgem"
uses: "shopify/cibuildgem/.github/actions/cibuildgem@main"
with:
step: "compile"
test:
timeout-minutes: 20
name: "Run the test suite"
needs: compile
strategy:
matrix:
os: ["macos-latest", "ubuntu-22.04"]
rubies: ["3.1", "3.2", "3.3", "3.4"]
type: ["cross", "native"]
runs-on: "${{ matrix.os }}"
steps:
- name: "Checkout code"
uses: "actions/checkout@v5"
- name: "Setup Ruby"
uses: "ruby/setup-ruby@v1"
with:
ruby-version: "${{ matrix.rubies }}"
bundler-cache: true
- name: "Run cibuildgem"
uses: "shopify/cibuildgem/.github/actions/cibuildgem@main"
with:
step: "test_${{ matrix.type }}"
install:
timeout-minutes: 5
name: "Verify the gem can be installed"
needs: test
strategy:
matrix:
os: ["macos-latest", "ubuntu-22.04"]
runs-on: "${{ matrix.os }}"
steps:
- name: "Setup Ruby"
uses: "ruby/setup-ruby@v1"
with:
ruby-version: "3.4.7"
- name: "Run cibuildgem"
uses: "shopify/cibuildgem/.github/actions/cibuildgem@main"
with:
step: "install"
release:
permissions:
id-token: write
contents: read
timeout-minutes: 5
if: ${{ inputs.release }}
name: "Release all gems with RubyGems"
needs: install
runs-on: "ubuntu-latest"
steps:
- name: "Setup Ruby"
uses: "ruby/setup-ruby@v1"
with:
ruby-version: "3.4.7"
- name: "Run cibuildgem"
uses: "shopify/cibuildgem/.github/actions/cibuildgem@main"
with:
step: "release"
8 changes: 7 additions & 1 deletion lib/stack_frames.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
# frozen_string_literal: true

require 'stack_frames/version'
require 'stack_frames/stack_frames'

begin
ruby_version = /(\d+\.\d+)/.match(RUBY_VERSION)
Copy link
Member Author

Choose a reason for hiding this comment

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

For now I'm going with the "standard" way of requiring the binary for fat gems. There was mention that the require will be slower for users using the non precompiled gem ruby/json#907 (comment) but I haven't found a good solution to this yet.

Copy link

@eregon eregon Dec 9, 2025

Choose a reason for hiding this comment

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

One extra thing to consider for the general pattern is this fat-gem require only makes sense on CRuby (RUBY_ENGINE == "ruby"), since RubyGems currently only supports requiring precompiled extensions for CRuby (ruby/rubygems#2945).
rubygems/rfcs#60 could solve that and maybe do the proper solution to ship a separate gem per Ruby major.minor (i.e. per ABI version), but it's unclear to me if and when it would be implemented.

IOW, it would be great to come up with a correct pattern for the fat-gem require which also does not cause an unnecessary LoadError.
https://github.com/ruby/psych/pull/406/files shows one solution, and that one has comments explaining how it works.

Copy link
Member Author

Choose a reason for hiding this comment

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

https://github.com/ruby/psych/pull/406/files shows one solution, and that one has comments explaining how it works.

I like this trick but Kou mentioned he'd prefer not to use it. ruby/json#907 (comment)

I'm currently discussing with my team at Shopify whether we want to fix this problem at the right level and resurrect the RFC you pointed out as well as go ahead and implement it once it gets finally approved by the community.

Copy link

Choose a reason for hiding this comment

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

This Regexp looks rather brittle without a start anchor like ^.
Also this is relying on MatchData#to_s which seems a bit unusual and somewhat inefficient.
How about using this?

RUBY_VERSION[/^\d+\.\d+/]

Copy link
Member Author

Choose a reason for hiding this comment

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

That sounds good to me. This seems more robust.

FWIW I copied it from Nokogiri https://github.com/sparklemotion/nokogiri/blob/7cb22acc66a9b9fffbdd33f9e0bd9bbc27dca497/lib/nokogiri/extension.rb#L6-L7

require "stack_frames/#{ruby_version}/stack_frames"
rescue LoadError
require "stack_frames/stack_frames"
end

StackFrames::Frame.singleton_class.class_eval do
private(:new)
Expand Down