Class: Tebako::RuntimeDescriptor

Inherits:
Object
  • Object
show all
Defined in:
lib/tebako/runtime_descriptor.rb

Overview

Versioned machine-readable identity and capabilities of a Tebako runtime.

Constant Summary collapse

SCHEMA_VERSION =
1
PACKAGE_FORMATS =
{ "monolithic" => 1, "layered" => 1 }.freeze
RUNTIME_SOURCE_PATHS =
%w[
  CMakeLists.txt
  cmake
  include
  src
  lib/tebako/build_helpers.rb
  lib/tebako/codegen.rb
  lib/tebako/content_manifest.rb
  lib/tebako/deploy_helper.rb
  lib/tebako/error.rb
  lib/tebako/filesystem_cache.rb
  lib/tebako/generated
  lib/tebako/native_gem_cache.rb
  lib/tebako/options_manager.rb
  lib/tebako/packager
  lib/tebako/packager.rb
  lib/tebako/ruby_builder.rb
  lib/tebako/ruby_version.rb
  lib/tebako/scenario_manager.rb
  lib/tebako/stripper.rb
  lib/tebako/version.rb
].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data) ⇒ RuntimeDescriptor

Returns a new instance of RuntimeDescriptor.



96
97
98
99
# File 'lib/tebako/runtime_descriptor.rb', line 96

def initialize(data)
  @data = data.transform_keys(&:to_s)
  validate_schema!
end

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data.



47
48
49
# File 'lib/tebako/runtime_descriptor.rb', line 47

def data
  @data
end

Class Method Details

.build(options_manager) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/tebako/runtime_descriptor.rb', line 50

def build(options_manager)
  identity_inputs = {
    "schema_version" => SCHEMA_VERSION,
    "tebako_version" => Tebako::VERSION,
    "ruby_version" => options_manager.ruby_ver,
    "ruby_api_version" => options_manager.rv.api_version,
    "platform" => RUBY_PLATFORM,
    "architecture" => RbConfig::CONFIG["host_cpu"],
    "host_os" => RbConfig::CONFIG["host_os"],
    "compression_level" => options_manager.compression_level,
    "log_level" => options_manager.l_level,
    "package_formats" => PACKAGE_FORMATS
  }
  identity_inputs["build_environment"] = build_environment
  identity_inputs["source_identity"] = source_identity(options_manager.source)
  identity = Digest::SHA256.hexdigest(JSON.generate(identity_inputs))
  new(identity_inputs.merge("runtime_identity" => "tebako-runtime-v1-#{identity}"))
end

.load(path) ⇒ Object



69
70
71
72
73
# File 'lib/tebako/runtime_descriptor.rb', line 69

def load(path)
  new(JSON.parse(File.binread(path)))
rescue JSON::ParserError, SystemCallError => e
  raise Tebako::Error.new("Unable to read runtime descriptor '#{path}': #{e.message}", 120)
end

.path_for(runtime) ⇒ Object



75
76
77
# File 'lib/tebako/runtime_descriptor.rb', line 75

def path_for(runtime)
  "#{runtime}.runtime.json"
end

Instance Method Details

#compatible!(ruby_version:, ruby_api_version:, platform: RUBY_PLATFORM, package_format: nil) ⇒ Object

Raises:



115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/tebako/runtime_descriptor.rb', line 115

def compatible!(ruby_version:, ruby_api_version:, platform: RUBY_PLATFORM, package_format: nil)
  mismatches = []
  mismatches << "Ruby #{@data["ruby_version"]} (requested #{ruby_version})" if @data["ruby_version"] != ruby_version
  if @data["ruby_api_version"] != ruby_api_version
    mismatches << "Ruby ABI #{@data["ruby_api_version"]} (requested #{ruby_api_version})"
  end
  mismatches << "platform #{@data["platform"]} (host #{platform})" if @data["platform"] != platform
  if package_format && !@data.fetch("package_formats", {}).key?(package_format)
    mismatches << "package format #{package_format}"
  end
  return true if mismatches.empty?

  raise Tebako::Error.new("Runtime is incompatible: #{mismatches.join(", ")}", 120)
end

#identityObject



101
102
103
# File 'lib/tebako/runtime_descriptor.rb', line 101

def identity
  @data.fetch("runtime_identity")
end

#write(path) ⇒ Object



105
106
107
108
109
110
111
112
113
# File 'lib/tebako/runtime_descriptor.rb', line 105

def write(path)
  FileUtils.mkdir_p(File.dirname(File.expand_path(path)))
  temporary = "#{path}.#{Process.pid}.#{SecureRandom.hex(6)}.tmp"
  File.binwrite(temporary, JSON.pretty_generate(@data))
  File.rename(temporary, path)
  path
ensure
  FileUtils.rm_f(temporary) if temporary
end