Module: Bundler::Spinel::Scaffold

Defined in:
lib/bundler/spinel/engine_installer.rb

Overview

Scaffolds a minimal Spinel project so onboarding is ‘bundle install && spinel-compat init && bin/build` (spinelgems#9, stretch). Writes a Gemfile with the engine marker + a framework gem, a hello entrypoint, and a bin/build that provisions the engine, vendors deps, and compiles.

Class Method Summary collapse

Class Method Details

.app_rbObject



209
210
211
212
213
214
215
216
217
# File 'lib/bundler/spinel/engine_installer.rb', line 209

def app_rb
  <<~RUBY
    require "tep"

    get "/" do
      "hello from a Spinel-compiled Tep app\\n"
    end
  RUBY
end

.build_shObject



219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/bundler/spinel/engine_installer.rb', line 219

def build_sh
  <<~SH
    #!/usr/bin/env bash
    # Provision the Spinel compiler, vendor deps where Spinel finds them,
    # and compile app.rb to a native binary.
    set -e
    spinel-compat install-engine          # fetch+build the pinned engine (cached)
    spinel-compat vendor                  # place deps + write deps.rb
    tep build app.rb -o app               # compile -> ./app
    echo "built ./app — run it with: ./app -p 4567"
  SH
end

.gemfileObject



193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/bundler/spinel/engine_installer.rb', line 193

def gemfile
  <<~RUBY
    source "https://rubygems.org"

    # Spinel is the engine: code here is compiled ahead-of-time to a native
    # binary, not run on CRuby. `engine_version` is advisory and must be a
    # version literal (bundler parses it as a Gem requirement); the actual
    # engine revision install-engine builds is pinned in ./SPINEL_PIN.
    ruby "3.3.0", engine: "spinel", engine_version: "0.0.0"

    # The web framework — Sinatra-style, compiles via Spinel. Until tep is on
    # RubyGems, point at the repo:  gem "tep", git: "https://github.com/OriPekelman/tep.git"
    gem "tep"
  RUBY
end

.gitignoreObject



232
233
234
235
236
237
238
239
# File 'lib/bundler/spinel/engine_installer.rb', line 232

def gitignore
  <<~TXT
    /app
    /vendor
    *.o
    *.bin
  TXT
end

.init(dir, out: $stdout, rev: nil) ⇒ Object



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/bundler/spinel/engine_installer.rb', line 160

def init(dir, out: $stdout, rev: nil)
  FileUtils.mkdir_p(dir)
  engine_rev = rev || EngineInstaller::DEFAULT_REV
  write(out, File.join(dir, "Gemfile"), gemfile)
  # The engine revision is a git SHA — NOT a valid `engine_version:` (bundler
  # parses that as a Gem version requirement and `bundle lock` errors on a
  # SHA). So the rev lives in a SPINEL_PIN file, which `install-engine`
  # reads; the Gemfile keeps a version-literal advisory marker.
  write(out, File.join(dir, "SPINEL_PIN"), "#{engine_rev}\n")
  write(out, File.join(dir, "app.rb"), app_rb)
  bin = File.join(dir, "bin", "build")
  FileUtils.mkdir_p(File.dirname(bin))
  write(out, bin, build_sh)
  File.chmod(0o755, bin)
  write(out, File.join(dir, ".gitignore"), gitignore)
  out.puts ""
  out.puts "Scaffolded a Spinel + Tep project in #{dir}/"
  out.puts "Next:"
  out.puts "  cd #{dir}" unless File.expand_path(dir) == Dir.pwd
  out.puts "  bundle install        # resolves deps (gated by the compat ledger)"
  out.puts "  ./bin/build           # provisions Spinel, vendors deps, compiles app.rb"
  out.puts "  ./app -p 4567         # run the native binary"
end

.write(out, path, body) ⇒ Object



184
185
186
187
188
189
190
191
# File 'lib/bundler/spinel/engine_installer.rb', line 184

def write(out, path, body)
  if File.exist?(path)
    out.puts "  skip (exists): #{path}"
  else
    File.write(path, body)
    out.puts "  create: #{path}"
  end
end