microsandbox-rb 0.13.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +102 -1
- data/Cargo.lock +230 -258
- data/DESIGN.md +107 -18
- data/README.md +88 -12
- data/ext/microsandbox/Cargo.toml +23 -7
- data/ext/microsandbox/src/sandbox.rs +15 -2
- data/lib/microsandbox/ssh.rb +15 -2
- data/lib/microsandbox/version.rb +2 -2
- data/lib/microsandbox.rb +128 -10
- data/sig/microsandbox.rbs +3 -2
- metadata +1 -1
data/lib/microsandbox.rb
CHANGED
|
@@ -64,12 +64,13 @@ module Microsandbox
|
|
|
64
64
|
# Download and install the `msb` runtime + `libkrunfw` into
|
|
65
65
|
# `~/.microsandbox` (idempotent).
|
|
66
66
|
#
|
|
67
|
-
#
|
|
68
|
-
# runtime
|
|
69
|
-
#
|
|
70
|
-
#
|
|
71
|
-
#
|
|
72
|
-
#
|
|
67
|
+
# This gem is SDK-only: nothing is provisioned at build/install time. The
|
|
68
|
+
# runtime comes from the companion `microsandbox-rb-binaries` gem when it is
|
|
69
|
+
# installed (see {ensure_runtime!}); otherwise it is fetched into
|
|
70
|
+
# `~/.microsandbox` on first use. Call this explicitly to provision ahead of
|
|
71
|
+
# time (e.g. while baking a container image) so the first {Sandbox.create}
|
|
72
|
+
# doesn't pay the download. Not needed — and not used — when the binaries
|
|
73
|
+
# gem supplies the runtime.
|
|
73
74
|
# @return [nil]
|
|
74
75
|
def install
|
|
75
76
|
Native.install
|
|
@@ -102,10 +103,14 @@ module Microsandbox
|
|
|
102
103
|
|
|
103
104
|
# Ensure the `msb` runtime + `libkrunfw` are present *and version-matched*,
|
|
104
105
|
# provisioning them on first use if not. Called automatically by
|
|
105
|
-
# {Sandbox.create}/{Sandbox.start} so
|
|
106
|
-
#
|
|
106
|
+
# {Sandbox.create}/{Sandbox.start} so a freshly installed gem gets a working
|
|
107
|
+
# runtime without a manual {install} step.
|
|
107
108
|
#
|
|
108
|
-
# Runs at most once per process.
|
|
109
|
+
# Runs at most once per process. When the companion `microsandbox-rb-binaries`
|
|
110
|
+
# gem supplies the runtime (it was activated at load time and its `msb` is
|
|
111
|
+
# what the resolver now returns from {runtime_path}), nothing is downloaded
|
|
112
|
+
# or touched in `~/.microsandbox` — the bundled binaries are already the
|
|
113
|
+
# matching version. Opt out of the download by setting
|
|
109
114
|
# `MICROSANDBOX_NO_AUTO_INSTALL` (e.g. air-gapped hosts that provision the
|
|
110
115
|
# runtime out of band); the runtime is then left untouched and a missing or
|
|
111
116
|
# stale one surfaces at the operation itself.
|
|
@@ -129,6 +134,14 @@ module Microsandbox
|
|
|
129
134
|
# uses the same lazy env/profile/config ladder every operation already
|
|
130
135
|
# consults, so this adds no work for local hosts (the common case).
|
|
131
136
|
return if default_backend_kind == :cloud
|
|
137
|
+
# The binaries gem won the resolver: its vendored msb (and the libkrunfw
|
|
138
|
+
# beside it) are exactly the version this gem was built for, so there is
|
|
139
|
+
# nothing to verify or download. (If `MSB_PATH` overrides it, the user owns
|
|
140
|
+
# the runtime and we fall through to the existing behaviour.)
|
|
141
|
+
if bundled_runtime_active?
|
|
142
|
+
@runtime_ready = true
|
|
143
|
+
return
|
|
144
|
+
end
|
|
132
145
|
# Opted out: the caller manages the runtime out of band, so don't fetch,
|
|
133
146
|
# verify, or repair it here. Memoize the decision (the env var is stable for
|
|
134
147
|
# the process); the operation resolves `msb` itself and surfaces any problem.
|
|
@@ -139,7 +152,8 @@ module Microsandbox
|
|
|
139
152
|
|
|
140
153
|
unless installed?
|
|
141
154
|
warn "[microsandbox] runtime (msb + libkrunfw) not found; " \
|
|
142
|
-
"downloading to ~/.microsandbox (set MICROSANDBOX_NO_AUTO_INSTALL to skip
|
|
155
|
+
"downloading to ~/.microsandbox (set MICROSANDBOX_NO_AUTO_INSTALL to skip, " \
|
|
156
|
+
"or install the microsandbox-rb-binaries gem to ship it with your bundle)..."
|
|
143
157
|
end
|
|
144
158
|
install
|
|
145
159
|
@runtime_ready = true
|
|
@@ -155,9 +169,17 @@ module Microsandbox
|
|
|
155
169
|
# resolver, below only the `MSB_PATH` environment variable). Process-level
|
|
156
170
|
# and set-once: a second call is silently ignored, and the `MSB_PATH`
|
|
157
171
|
# environment variable still wins. Mirrors {libkrunfw_path=}.
|
|
172
|
+
#
|
|
173
|
+
# The companion `microsandbox-rb-binaries` gem claims this same slot when
|
|
174
|
+
# `require "microsandbox"` activates it, so with that gem installed this
|
|
175
|
+
# setter is a no-op — use `MSB_PATH` to override a bundled runtime.
|
|
158
176
|
# @param path [String]
|
|
159
177
|
# @return [void]
|
|
160
178
|
def runtime_path=(path)
|
|
179
|
+
if @bundled_msb_path && path.to_s != @bundled_msb_path
|
|
180
|
+
warn "[microsandbox] runtime_path= ignored: the microsandbox-rb-binaries gem already " \
|
|
181
|
+
"claimed the set-once SDK slot (#{@bundled_msb_path}); set MSB_PATH to override it"
|
|
182
|
+
end
|
|
161
183
|
Native.set_runtime_msb_path(path.to_s)
|
|
162
184
|
end
|
|
163
185
|
|
|
@@ -257,5 +279,101 @@ module Microsandbox
|
|
|
257
279
|
v = ENV["MICROSANDBOX_NO_AUTO_INSTALL"]
|
|
258
280
|
!v.nil? && !v.empty? && !%w[0 false no].include?(v.downcase)
|
|
259
281
|
end
|
|
282
|
+
|
|
283
|
+
# Wire the companion `microsandbox-rb-binaries` gem into the core resolver.
|
|
284
|
+
# Runs once, at `require "microsandbox"` time (like the Node SDK, which pushes
|
|
285
|
+
# its platform package's msb into the same set-once SDK slot at module load)
|
|
286
|
+
# so every entry point that spawns msb — not just {Sandbox.create} — sees it.
|
|
287
|
+
#
|
|
288
|
+
# The gem is optional and has no dependency edge to this one (cloud-only
|
|
289
|
+
# users skip the ~50 MB download; RubyGems has no optional dependencies), so
|
|
290
|
+
# discovery is by require: absent → nothing happens and the resolver's lower
|
|
291
|
+
# tiers (`~/.microsandbox`, then `PATH`) plus the first-use download take
|
|
292
|
+
# over. Present but built for a different upstream runtime → warn and skip
|
|
293
|
+
# it rather than hand the core a mismatched msb (a stale runtime passes an
|
|
294
|
+
# exists-check and then fails every create on a wire-protocol mismatch).
|
|
295
|
+
# Only `MSB_PATH` (env) outranks the slot claimed here.
|
|
296
|
+
#
|
|
297
|
+
# Never raises: a broken companion gem must not take `require "microsandbox"`
|
|
298
|
+
# down with it.
|
|
299
|
+
# @return [String, nil] the activated msb path
|
|
300
|
+
def activate_bundled_runtime!
|
|
301
|
+
@bundled_msb_path = nil
|
|
302
|
+
begin
|
|
303
|
+
# Pin the lockstep version when RubyGems (not Bundler) picks the gem, so
|
|
304
|
+
# a newer/older companion left around doesn't get activated over the
|
|
305
|
+
# matching one. Under Bundler the Gemfile already decides; a companion
|
|
306
|
+
# that isn't in the bundle raises here and `require` then fails below.
|
|
307
|
+
gem "microsandbox-rb-binaries", "= #{VERSION}"
|
|
308
|
+
rescue Gem::LoadError
|
|
309
|
+
# Not installed at this version — `require` settles it.
|
|
310
|
+
end
|
|
311
|
+
begin
|
|
312
|
+
require "microsandbox/binaries"
|
|
313
|
+
rescue LoadError
|
|
314
|
+
return nil
|
|
315
|
+
end
|
|
316
|
+
# A bare require activates the newest gem of ANY name that ships this
|
|
317
|
+
# feature path; only accept the companion gem itself, this gem's own tree
|
|
318
|
+
# (a source checkout, where Bundler's path gem spans the whole repo and so
|
|
319
|
+
# owns binaries/lib too), or a plain load path (RUBYLIB/-I) no gem owns.
|
|
320
|
+
owner = bundled_runtime_owner
|
|
321
|
+
if owner && !TRUSTED_BINARIES_OWNERS.include?(owner)
|
|
322
|
+
warn "[microsandbox] ignoring microsandbox/binaries provided by the #{owner} gem " \
|
|
323
|
+
"(only microsandbox-rb-binaries is trusted for the bundled runtime)"
|
|
324
|
+
return nil
|
|
325
|
+
end
|
|
326
|
+
# Lockstep gate on BOTH constants. The runtime tag is what the wire
|
|
327
|
+
# protocol depends on; the gem version is the documented contract
|
|
328
|
+
# ("install both at the same version") and also covers this file's own
|
|
329
|
+
# API/packaging — the `gem "…", "= VERSION"` pin above is best-effort (it
|
|
330
|
+
# raises under Bundler whenever the bundle picked any other version, and
|
|
331
|
+
# that is swallowed), so it cannot be what enforces it.
|
|
332
|
+
unless Binaries::VERSION == VERSION && Binaries::RUNTIME_VERSION == RUNTIME_VERSION
|
|
333
|
+
warn "[microsandbox] ignoring microsandbox-rb-binaries #{Binaries::VERSION} " \
|
|
334
|
+
"(runtime #{Binaries::RUNTIME_VERSION}): microsandbox-rb #{VERSION} " \
|
|
335
|
+
"(runtime #{RUNTIME_VERSION}) needs the companion gem at the same version. " \
|
|
336
|
+
"Install both gems at the same version; falling back to ~/.microsandbox."
|
|
337
|
+
return nil
|
|
338
|
+
end
|
|
339
|
+
msb = Binaries.msb_path
|
|
340
|
+
unless msb && Binaries.libkrunfw_path
|
|
341
|
+
warn "[microsandbox] microsandbox-rb-binaries #{Binaries::VERSION} is installed but " \
|
|
342
|
+
"carries no runtime under #{Binaries.root}; falling back to ~/.microsandbox."
|
|
343
|
+
return nil
|
|
344
|
+
end
|
|
345
|
+
Native.set_runtime_msb_path(msb)
|
|
346
|
+
@bundled_msb_path = msb
|
|
347
|
+
rescue StandardError, ScriptError => e
|
|
348
|
+
# ScriptError too: a corrupt or newer-syntax binaries.rb raises
|
|
349
|
+
# SyntaxError (not a StandardError) out of `require`, and the optional
|
|
350
|
+
# companion must never take `require "microsandbox"` down with it.
|
|
351
|
+
warn "[microsandbox] could not activate microsandbox-rb-binaries: #{e.class}: #{e.message}"
|
|
352
|
+
nil
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
# Gems allowed to provide `microsandbox/binaries` (see activate_bundled_runtime!).
|
|
356
|
+
TRUSTED_BINARIES_OWNERS = %w[microsandbox-rb-binaries microsandbox-rb].freeze
|
|
357
|
+
private_constant :TRUSTED_BINARIES_OWNERS
|
|
358
|
+
|
|
359
|
+
# Name of the loaded gem whose files define Microsandbox::Binaries, or nil
|
|
360
|
+
# when it came from a bare load path.
|
|
361
|
+
def bundled_runtime_owner
|
|
362
|
+
source = Binaries.method(:msb_path).source_location&.first
|
|
363
|
+
return nil unless source
|
|
364
|
+
spec = Gem.loaded_specs.values.find { |s| source.start_with?(File.join(s.full_gem_path, "")) }
|
|
365
|
+
spec&.name
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
# Whether the binaries gem's msb is what the resolver actually returns — i.e.
|
|
369
|
+
# it was activated and nothing higher in the ladder (`MSB_PATH`) overrides it.
|
|
370
|
+
def bundled_runtime_active?
|
|
371
|
+
return false unless @bundled_msb_path
|
|
372
|
+
runtime_path == @bundled_msb_path
|
|
373
|
+
rescue Microsandbox::Error
|
|
374
|
+
false
|
|
375
|
+
end
|
|
260
376
|
end
|
|
377
|
+
|
|
378
|
+
send(:activate_bundled_runtime!)
|
|
261
379
|
end
|
data/sig/microsandbox.rbs
CHANGED
|
@@ -653,8 +653,9 @@ module Microsandbox
|
|
|
653
653
|
|
|
654
654
|
class SshOps
|
|
655
655
|
def initialize: (untyped native) -> void
|
|
656
|
-
def open_client: (?user: String, ?term: String?, ?sftp: bool
|
|
656
|
+
def open_client: (?user: String, ?term: String?, ?sftp: bool,
|
|
657
|
+
?inactivity_timeout: Numeric?) ?{ (SshClient) -> untyped } -> untyped
|
|
657
658
|
def prepare_server: (?host_key_path: String?, ?authorized_keys_path: String?,
|
|
658
|
-
?user: String?, ?sftp: bool) -> SshServer
|
|
659
|
+
?user: String?, ?sftp: bool, ?inactivity_timeout: Numeric?) -> SshServer
|
|
659
660
|
end
|
|
660
661
|
end
|