diff --git a/.github/workflows/ruby-release.yml b/.github/workflows/ruby-release.yml
index f1fc25cb..fa179b0b 100644
--- a/.github/workflows/ruby-release.yml
+++ b/.github/workflows/ruby-release.yml
@@ -4,6 +4,16 @@ on:
push:
tags:
- ruby-v*
+ workflow_dispatch:
+ inputs:
+ dry_run:
+ description: "Build and smoke-test the gems without publishing them"
+ type: boolean
+ default: true
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
jobs:
cross-gem:
@@ -15,6 +25,7 @@ jobs:
matrix:
platform:
- aarch64-linux
+ - aarch64-linux-musl
- arm64-darwin
- x64-mingw-ucrt
- x86_64-darwin
@@ -31,6 +42,11 @@ jobs:
bundler-cache: true
working-directory: ./bindings/ruby
+ # `cross-gem` reads `rb_sys` version from the root `Gemfile.lock`, and
+ # falls back to the newest published one when it is missing.
+ - name: Expose Gemfile.lock for rb-sys-dock version detection
+ run: cp bindings/ruby/Gemfile.lock Gemfile.lock
+
- name: Compile native gem
id: cross-gem
uses: oxidize-rb/actions/cross-gem@v1.4.4
@@ -39,6 +55,22 @@ jobs:
ruby-versions: "3.2,3.3,3.4,4.0"
working-directory: ./bindings/ruby
+ # Pushes to RubyGems are irreversible.
+ - name: Smoke test
+ if: matrix.platform == 'x86_64-linux'
+ working-directory: ./bindings/ruby
+ env:
+ BUNDLE_GEMFILE: ""
+ run: |
+ gem install pkg/*.gem --local --no-document
+ ruby -e "
+ require 'css_inline'
+ html = '
Test
'
+ result = CSSInline.inline(html)
+ raise 'inlining failed' unless result.include?('style=\"color: red;\"')
+ puts 'smoke test OK'
+ "
+
- uses: actions/upload-artifact@v7
with:
name: cross-gem-${{ matrix.platform }}
@@ -48,6 +80,9 @@ jobs:
ruby-release:
needs: cross-gem
runs-on: ubuntu-22.04
+ env:
+ # A manual run from a branch has no version to release.
+ PUBLISH: ${{ !inputs.dry_run && startsWith(github.ref, 'refs/tags/') }}
steps:
- uses: actions/checkout@v7
@@ -69,7 +104,15 @@ jobs:
merge-multiple: true
path: ./bindings/ruby/pkg
+ - name: Build source gem
+ working-directory: ./bindings/ruby
+ run: |
+ gem build *.gemspec
+ mv css_inline-*.gem pkg/
+ ls -l pkg/
+
- name: GitHub Release
+ if: env.PUBLISH == 'true'
uses: softprops/action-gh-release@v3
with:
make_latest: false
@@ -78,15 +121,23 @@ jobs:
files: ./bindings/ruby/pkg/*.gem
- name: Publish to RubyGems
+ if: env.PUBLISH == 'true'
+ working-directory: ./bindings/ruby
run: |
mkdir -p $HOME/.gem
touch $HOME/.gem/credentials
chmod 0600 $HOME/.gem/credentials
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
- cd ./bindings/ruby
- gem build *.gemspec
- for gem in *.gem pkg/*.gem; do
+ for gem in pkg/*.gem; do
gem push "$gem"
done
env:
GEM_HOST_API_KEY: "${{ secrets.RUBYGEMS_API_KEY }}"
+
+ - name: Upload gems (no publish)
+ if: env.PUBLISH != 'true'
+ uses: actions/upload-artifact@v7
+ with:
+ name: gems
+ path: ./bindings/ruby/pkg/*.gem
+ if-no-files-found: error
diff --git a/bindings/ruby/CHANGELOG.md b/bindings/ruby/CHANGELOG.md
index 84d66a86..afe99caf 100644
--- a/bindings/ruby/CHANGELOG.md
+++ b/bindings/ruby/CHANGELOG.md
@@ -2,6 +2,11 @@
## [Unreleased]
+### Added
+
+- Precompiled native gems for Linux (glibc & musl, x86-64 & aarch64), macOS (x86-64 & arm64), and Windows (`x64-mingw-ucrt`). Installing no longer requires a Rust toolchain on these platforms.
+- Support for Ruby 4.0.
+
## [0.21.2] - 2026-08-24
### Fixed
diff --git a/bindings/ruby/Rakefile b/bindings/ruby/Rakefile
index 328a7386..73872812 100644
--- a/bindings/ruby/Rakefile
+++ b/bindings/ruby/Rakefile
@@ -12,12 +12,15 @@ spec.required_ruby_version = nil
spec.required_rubygems_version = nil
spec.extensions.clear
spec.files -= Dir["ext/**/*"]
+# `rb_sys` only builds the extension.
+spec.dependencies.reject! { |d| d.name == "rb_sys" }
Rake::ExtensionTask.new("css_inline", spec) do |c|
c.lib_dir = "lib/css_inline"
c.cross_compile = true
c.cross_platform = [
"aarch64-linux",
+ "aarch64-linux-musl",
"arm64-darwin",
"x64-mingw-ucrt",
"x64-mingw32",