| name | smbcloud-ruby-native-gem |
| description | Use when building, packaging, or publishing smbCloud Ruby gems backed by Rust native extensions through Magnus and rb_sys, especially under sdk/gems/model and sdk/gems/auth. Covers gem layout, path wiring to workspace crates, rake build/compile flows, pkg output, .gitignore conventions, and RubyGems release preflight. |
smbCloud Ruby Native Gem
Use this skill when work touches smbCloud Ruby gems that wrap Rust crates through Magnus.
Applies to:
sdk/gems/model
sdk/gems/auth
- new gems following the same pattern
ext/*/Cargo.toml path wiring
auth.gemspec or model.gemspec
Rakefile, extconf.rb, lib/*.rb, sig/*.rbs
- local build and RubyGems publish steps
Source of truth
For each gem, inspect these files first:
sdk/gems/<name>/<name>.gemspec
sdk/gems/<name>/Rakefile
sdk/gems/<name>/ext/<name>/Cargo.toml
sdk/gems/<name>/ext/<name>/extconf.rb
sdk/gems/<name>/lib/<name>.rb
sdk/gems/<name>/lib/<name>/version.rb
sdk/gems/<name>/.gitignore
The Rust crate under crates/ remains the API source of truth. The gem should stay a thin Ruby-facing adapter.
Expected layout
Use the same structure as sdk/gems/model and sdk/gems/auth:
- workspace
Cargo.toml at gem root
- native extension crate at
ext/<name>
- Ruby entrypoint at
lib/<name>.rb
- version file at
lib/<name>/version.rb
- type signature file under
sig/
Rakefile using RbSys::ExtensionTask
extconf.rb using create_rust_makefile
Do not invent a different packaging layout unless there is a strong reason.
Cargo path wiring
Be careful with relative paths from sdk/gems/<name>/ext/<name>/Cargo.toml to workspace crates.
From that directory, crates/... is typically five levels up:
./../../../../../crates/<crate-name>
Do not assume four levels. Verify the actual path before building.
Ruby API design
Keep the gem framework-agnostic.
Preferred layering:
- Rust crate owns transport and domain logic
- native Magnus extension bridges into Ruby
- plain Ruby wrapper exposes the public API
For reusable SDKs, prefer a client object such as:
SmbCloud::Auth::Client.new(...)
Keep Rails-specific helpers, sessions, and controller concerns out of the core gem. If needed later, create a separate Rails adapter gem.
Build workflow
Use the standard rake tasks.
From sdk/gems/<name>:
bundle install
bundle exec rake compile
bundle exec rake build
Expected behavior:
- native build output goes under
target/
- packaged gem goes under
pkg/
For Rust-only verification, also use:
cargo check
cargo fmt --manifest-path ext/<name>/Cargo.toml
Prefer formatting the extension crate directly if the parent workspace has unrelated manifest issues.
.gitignore conventions
Match the sdk/gems/model pattern.
Ignore:
/.bundle/
/pkg/
/tmp/
target/
*.bundle
- native object outputs such as
*.so, *.o, *.a
mkmf.log
Do not track built .gem artifacts in git. They belong in pkg/ and should be ignored.
Release preflight
Before publishing:
- confirm the version in
lib/<name>/version.rb
- build the gem with
bundle exec rake build
- verify the artifact exists in
pkg/
- inspect warnings from
gem build or rake build
- confirm RubyGems credentials exist
Credentials can come from either:
~/.gem/credentials
GEM_HOST_API_KEY
Without one of those, gem push will fail.
Publish
From sdk/gems/<name>:
bundle exec gem push pkg/<name>-<version>.gem
Do not claim a publish succeeded unless the push completed successfully.
Common mistakes
- wrong relative path from
ext/<name>/Cargo.toml to crates/...
- exposing Ruby methods that the native extension does not actually export
- putting release artifacts in git
- making the gem Rails-specific when the crate should stay generic
- using
gem build ad hoc while ignoring the repo's rake build and pkg/ convention
- attempting
gem push without RubyGems credentials configured