Open maxirmx opened 3 months ago
Based on the provided implementation of Tebako, here's a proposal for splitting off the Runtime component to allow separate downloading and execution of multiple packaged Runtimes:
Modify the Tebako packaging process:
Update the tebako.yaml file:
Add a runtime
section to specify the required Ruby version:
runtime:
ruby_version: 3.2.4
Modify the Tebako executable:
~/.tebako/ruby/<version>/
.Implement a runtime manager:
tebako
CLI tool.Update the Tebako loader:
Implement runtime download and caching:
~/.tebako/ruby/<version>/
.Modify the packaging process:
Update the tebako
CLI:
tebako runtime install 3.2.4
, tebako runtime list
).press
command to package applications without bundling the runtime.Implement runtime isolation:
Update documentation and guides:
By implementing these changes, Tebako would allow for more flexible runtime management, reduced package sizes, and easier updates to runtime versions. Users could have multiple Ruby versions installed and easily switch between them based on the requirements of each packaged application.
Here's a proposed implementation for the runtime manager in Ruby. This implementation would be part of the Tebako gem and could be invoked via the CLI or used programmatically.
require 'fileutils'
require 'open-uri'
require 'json'
require 'digest'
module Tebako
class RuntimeManager
RUNTIME_BASE_URL = "https://github.com/tamatebako/tebako-runtimes/releases/download"
RUNTIME_MANIFEST_URL = "https://api.github.com/repos/tamatebako/tebako-runtimes/releases/latest"
RUNTIME_DIR = File.expand_path("~/.tebako/ruby")
def initialize
FileUtils.mkdir_p(RUNTIME_DIR)
end
def install(version)
if installed?(version)
puts "Ruby #{version} is already installed."
return
end
puts "Installing Ruby #{version}..."
download_runtime(version)
puts "Ruby #{version} has been installed successfully."
end
def uninstall(version)
if !installed?(version)
puts "Ruby #{version} is not installed."
return
end
puts "Uninstalling Ruby #{version}..."
FileUtils.rm_rf(File.join(RUNTIME_DIR, version))
puts "Ruby #{version} has been uninstalled successfully."
end
def list
installed_versions = Dir.glob(File.join(RUNTIME_DIR, "*")).map { |f| File.basename(f) }
puts "Installed Ruby versions:"
installed_versions.each { |v| puts " - #{v}" }
end
def installed?(version)
Dir.exist?(File.join(RUNTIME_DIR, version))
end
def ensure_runtime(version)
install(version) unless installed?(version)
end
private
def download_runtime(version)
manifest = fetch_manifest
runtime_info = manifest['assets'].find { |asset| asset['name'] == "ruby-#{version}.tar.gz" }
if runtime_info.nil?
raise "Runtime for Ruby #{version} not found in the manifest."
end
download_url = runtime_info['browser_download_url']
expected_sha256 = runtime_info['sha256']
target_dir = File.join(RUNTIME_DIR, version)
FileUtils.mkdir_p(target_dir)
URI.open(download_url) do |remote_file|
File.open(File.join(target_dir, "ruby-#{version}.tar.gz"), 'wb') do |local_file|
local_file.write(remote_file.read)
end
end
verify_integrity(File.join(target_dir, "ruby-#{version}.tar.gz"), expected_sha256)
system("tar -xzf #{File.join(target_dir, "ruby-#{version}.tar.gz")} -C #{target_dir}")
FileUtils.rm(File.join(target_dir, "ruby-#{version}.tar.gz"))
end
def fetch_manifest
JSON.parse(URI.open(RUNTIME_MANIFEST_URL).read)
end
def verify_integrity(file_path, expected_sha256)
actual_sha256 = Digest::SHA256.file(file_path).hexdigest
if actual_sha256 != expected_sha256
FileUtils.rm(file_path)
raise "Integrity check failed for downloaded runtime."
end
end
end
end
This RuntimeManager
class provides the following functionality:
install(version)
: Downloads and installs a specific Ruby version.uninstall(version)
: Removes a specific Ruby version.list
: Shows all installed Ruby versions.installed?(version)
: Checks if a specific Ruby version is installed.ensure_runtime(version)
: Installs a runtime if it's not already installed.The manager downloads runtime packages from a GitHub releases page, verifies their integrity using SHA256 checksums, and extracts them to ~/.tebako/ruby/<version>/
.
To integrate this with the Tebako CLI, you could add new commands like this:
module Tebako
class CLI < Thor
desc "runtime SUBCOMMAND ...ARGS", "Manage Tebako runtimes"
subcommand "runtime", Runtime
class Runtime < Thor
desc "install VERSION", "Install a specific Ruby runtime"
def install(version)
RuntimeManager.new.install(version)
end
desc "uninstall VERSION", "Uninstall a specific Ruby runtime"
def uninstall(version)
RuntimeManager.new.uninstall(version)
end
desc "list", "List installed Ruby runtimes"
def list
RuntimeManager.new.list
end
end
end
end
This implementation allows users to manage Tebako runtimes using commands like:
tebako runtime install 3.2.4
tebako runtime uninstall 3.2.4
tebako runtime list
To use this runtime manager in the Tebako packaging and execution process:
RuntimeManager#ensure_runtime
to install it if necessary, and then use that version to run the packaged application.This approach provides flexibility in managing multiple Ruby versions and allows for easy updates to runtimes without rebuilding packaged applications.
Use runtime as a base and attach tebako package to it.