1 ---
2 name: smbcloud-ruby-native-gem
3 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.
4 ---
5
6 # smbCloud Ruby Native Gem
7
8 Use this skill when work touches smbCloud Ruby gems that wrap Rust crates through Magnus.
9
10 Applies to:
11
12 - `sdk/gems/model`
13 - `sdk/gems/auth`
14 - new gems following the same pattern
15 - `ext/*/Cargo.toml` path wiring
16 - `auth.gemspec` or `model.gemspec`
17 - `Rakefile`, `extconf.rb`, `lib/*.rb`, `sig/*.rbs`
18 - local build and RubyGems publish steps
19
20 ## Source of truth
21
22 For each gem, inspect these files first:
23
24 - `sdk/gems/<name>/<name>.gemspec`
25 - `sdk/gems/<name>/Rakefile`
26 - `sdk/gems/<name>/ext/<name>/Cargo.toml`
27 - `sdk/gems/<name>/ext/<name>/extconf.rb`
28 - `sdk/gems/<name>/lib/<name>.rb`
29 - `sdk/gems/<name>/lib/<name>/version.rb`
30 - `sdk/gems/<name>/.gitignore`
31
32 The Rust crate under `crates/` remains the API source of truth. The gem should stay a thin Ruby-facing adapter.
33
34 ## Expected layout
35
36 Use the same structure as `sdk/gems/model` and `sdk/gems/auth`:
37
38 - workspace `Cargo.toml` at gem root
39 - native extension crate at `ext/<name>`
40 - Ruby entrypoint at `lib/<name>.rb`
41 - version file at `lib/<name>/version.rb`
42 - type signature file under `sig/`
43 - `Rakefile` using `RbSys::ExtensionTask`
44 - `extconf.rb` using `create_rust_makefile`
45
46 Do not invent a different packaging layout unless there is a strong reason.
47
48 ## Cargo path wiring
49
50 Be careful with relative paths from `sdk/gems/<name>/ext/<name>/Cargo.toml` to workspace crates.
51
52 From that directory, `crates/...` is typically five levels up:
53
54 - `./../../../../../crates/<crate-name>`
55
56 Do not assume four levels. Verify the actual path before building.
57
58 ## Ruby API design
59
60 Keep the gem framework-agnostic.
61
62 Preferred layering:
63
64 1. Rust crate owns transport and domain logic
65 2. native Magnus extension bridges into Ruby
66 3. plain Ruby wrapper exposes the public API
67
68 For reusable SDKs, prefer a client object such as:
69
70 - `SmbCloud::Auth::Client.new(...)`
71
72 Keep Rails-specific helpers, sessions, and controller concerns out of the core gem. If needed later, create a separate Rails adapter gem.
73
74 ## Build workflow
75
76 Use the standard rake tasks.
77
78 From `sdk/gems/<name>`:
79
80 - `bundle install`
81 - `bundle exec rake compile`
82 - `bundle exec rake build`
83
84 Expected behavior:
85
86 - native build output goes under `target/`
87 - packaged gem goes under `pkg/`
88
89 For Rust-only verification, also use:
90
91 - `cargo check`
92 - `cargo fmt --manifest-path ext/<name>/Cargo.toml`
93
94 Prefer formatting the extension crate directly if the parent workspace has unrelated manifest issues.
95
96 ## .gitignore conventions
97
98 Match the `sdk/gems/model` pattern.
99
100 Ignore:
101
102 - `/.bundle/`
103 - `/pkg/`
104 - `/tmp/`
105 - `target/`
106 - `*.bundle`
107 - native object outputs such as `*.so`, `*.o`, `*.a`
108 - `mkmf.log`
109
110 Do not track built `.gem` artifacts in git. They belong in `pkg/` and should be ignored.
111
112 ## Release preflight
113
114 Before publishing:
115
116 1. confirm the version in `lib/<name>/version.rb`
117 2. build the gem with `bundle exec rake build`
118 3. verify the artifact exists in `pkg/`
119 4. inspect warnings from `gem build` or `rake build`
120 5. confirm RubyGems credentials exist
121
122 Credentials can come from either:
123
124 - `~/.gem/credentials`
125 - `GEM_HOST_API_KEY`
126
127 Without one of those, `gem push` will fail.
128
129 ## Publish
130
131 From `sdk/gems/<name>`:
132
133 - `bundle exec gem push pkg/<name>-<version>.gem`
134
135 Do not claim a publish succeeded unless the push completed successfully.
136
137 ## Common mistakes
138
139 - wrong relative path from `ext/<name>/Cargo.toml` to `crates/...`
140 - exposing Ruby methods that the native extension does not actually export
141 - putting release artifacts in git
142 - making the gem Rails-specific when the crate should stay generic
143 - using `gem build` ad hoc while ignoring the repo's `rake build` and `pkg/` convention
144 - attempting `gem push` without RubyGems credentials configured